A method that applies transforms in parallel to all elements and returns an array of return values that maintain their order

Overview

title

import Foundation

private let parallelQueue = DispatchQueue(label: "Sequence#parallelMapQueue", attributes: .concurrent)
extension Sequence {
  
  // parallelMap
  //Apply transform in parallel to all elements and return an array of return values that maintain their order
  //
  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() }
  }
}

Execution example


print(
  (0...10)
    .parallelMap { i -> Int in
       let t = UInt32([0, 2, 3, 5].randomElement()!)
       sleep(t)
       print(i, t)
       return i + 1
  }
)

//Output example
//
// 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]

It can be seen that they are executed separately (parallel) and that the order of the return values is maintained.

Recommended Posts

A method that applies transforms in parallel to all elements and returns an array of return values that maintain their order
A program (Java) that outputs the sum of odd and even numbers in an array
How to specify an array in the return value / argument of the method in the CORBA IDL file
Cast an array of Strings to a List of Integers in Java
Creating an ArrayList that allows you to throw in and retrieve the coordinates of a two-dimensional plane
How to test a private method in Java and partially mock that method
[Swift] How to get the number of elements in an array (super basic)
How to make a judgment method to search for an arbitrary character in an array
Rails6 I want to make an array of values with a check box
Pass arguments to the method and receive the result of the operation as a return value
[Rails] How to temporarily save the request URL of a user who is not logged in and return to that URL after logging in