The easiest way to run a parallel loop is concurrentPerform (formerly called dispatch_apply , see Running Loop Iterations in the Concurrency Programming Guide). But no, there is no map version that does this for you. You have to do it yourself.
For example, you can write an extension to perform parallel tasks:
extension Array { public func concurrentMap<T>(_ transform: (Element) -> T) -> [T] { var results = [Int: T]() let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".sync", attributes: .concurrent) DispatchQueue.concurrentPerform(iterations: count) { index in let result = transform(self[index]) queue.async { results[index] = result } } return queue.sync(flags: .barrier) { (0 ..< results.count).map { results[$0]! } } } }
Note:
This will block the thread from which you are calling it (as well as the non-competitive map ), so be sure to send it to the background.
It is necessary to ensure sufficient work on each thread to justify the overhead of managing all of these threads. (For example, simply calling xor for a loop is not enough, and you will find that it is actually slower than uncompetitive execution.) In these cases, make sure that you step (see "Improving the loop code" , which balances the amount of work by one parallel block). For example, instead of doing 5,000 iterations of one extremely simple operation, do 10 iterations of 500 operations per cycle. You may need to experiment with suitable step values.
While I suspect you do not need this discussion, for readers unfamiliar with concurrentPerform (formerly known as dispatch_apply ), I will illustrate its use below. For a more complete discussion of this topic, see the links above.
For example, consider something much more complex than a simple xor (because with something simple, the overhead outweighs any resulting performance), for example, the naive Fibonacci implementation:
func fibonacci(_ n: Int) -> Int { if n == 0 || n == 1 { return n } return fibonacci(n - 1) + fibonacci(n - 2) }
If you have an array of Int values ββthat you would like to calculate, not:
let results = array.map { fibonacci($0) }
You can:
var results = [Int](count: array.count, repeatedValue: 0) DispatchQueue.concurrentPerform(iterations: array.count) { index in let result = self.fibonacci(array[index]) synchronize.update { results[index] = result } // use whatever synchronization mechanism you want }
Or, if you require functional execution, you can use this extension I, above:
let results = array.concurrentMap { fibonacci($0) }
For Swift 2, see the previous version of this answer .