Titre
import Foundation
private let parallelQueue = DispatchQueue(label: "Sequence#parallelMapQueue", attributes: .concurrent)
extension Sequence {
  
  // parallelMap
  //Appliquer la transformation en parallèle à tous les éléments et renvoyer un tableau de valeurs de retour qui conservent leur ordre
  //
  func parallelMap<T>(_ transform: @escaping (Element) throws -> T) rethrows -> [T] {
  
    let group = DispatchGroup()
    let semaphore = DispatchSemaphore(value: 1)
    
    var result: [(Int, Result<T, Error>)] = []
    
    zip(0..., self)
      .forEach { i, v in
        
        parallelQueue.async(group: group) {
          
          let r = Result { try transform(v) }
          
          semaphore.wait()
          defer { semaphore.signal() }
          
          result.append((i, r))
        }
    }
    
    group.wait()
    
    return try result
            .sorted { $0.0 < $1.0 }
            .map { try $0.1.get() }
  }
}
print(
  (0...10)
    .parallelMap { i -> Int in
       let t = UInt32([0, 2, 3, 5].randomElement()!)
       sleep(t)
       print(i, t)
       return i + 1
  }
)
//Exemple de sortie
//
// 0 0
// 4 0
// 10 0
// 1 2
// 2 2
// 3 2
// 5 2
// 7 2
// 6 3
// 9 3
// 8 5
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
On voit qu'ils sont exécutés séparément (en parallèle) et que l'ordre des valeurs de retour est conservé.
Recommended Posts