Categories
Dev

Multi-core array operations in Swift

I finally had a reason to use DispatchQueue.concurrentPerform to spread some chunks of work across multiple cores. There’s something very satisfying about filling up CPU cores with work!

So with a bit of help from StackOverflow I came up with this Array extension for using map and for-each with a simple API.

The functions themselves are synchronous, but DispatchQueue.concurrentPerform does its magic and runs the passed in closures across the cores.

Here’s the code. Got a suggestion? Let me know on the Gist.


Array+Concurrency.swift

public extension Array {
    /// Synchronous
    func concurrentMap(transform: @escaping (Element) -> T) -> [T] {
        let result = UnsafeMutablePointer.allocate(capacity: count)

        DispatchQueue.concurrentPerform(iterations: count) { i in
            result.advanced(by: i).initialize(to: transform(self[i]))
        }
        
        let finalResult = Array(UnsafeBufferPointer(start: result, count: count))
        result.deallocate()
        
        return finalResult
    }
    
    /// Synchronous
    func concurrentForEach(action: @escaping (Element) -> Void) {
        _ = concurrentMap { _ = action($0) }
    }
} 

Usage

// Works just like regular `map` and `forEach`.

let things = [1, 2, 3, 4]

// 1
// 2
// 3
// 4
things.concurrentForEach {
    print($0)
}

let multipliedByTwo = things.concurrentMap { $0 * 2 } // [2, 4, 6, 8]