Collecting concurrentPerform(iterations:) Results in a Swift Array
Useful pattern for aggregating the results of parallel work in Swift:
let result = Array(unsafeUninitializedCapacity: count) { (buffer) in DispatchQueue.concurrentPerform(iterations: count) { (idx) in buffer[idx] = processItem(idx) } }Avoids making an extra buffer copy
If you make the
Arrayup front and try to operate directly on it instead of theUnsafeMutableBufferPointerin that initializer, each thread will get its own copy due to copy-on-write, which generally is not what you wanted.
I would not trust it [with small array elements]. Aligned word-sized non-float things are your friends when dealing with concurrency. If you’re not sure, try TSAN, and consider just using a lock.
Previously:
- High Performance Numeric Programming With Swift
- Underused and Overused GCD Patterns
- Swift 5 Exclusivity Enforcement
Update (2026-02-20): For objects and other types that use ARC, directly assigning into the buffer as shown above will crash in swift_unknownObjectRelease() as Swift tries to release the garbage memory that was in that position in the buffer. You should instead use:
buffer.initializeElement(at: idx, to: processItem(idx))
The original tweets have been deleted, so perhaps I’m missing something from the context, but the part about each thread getting its own copy if you make an Array up front does not sound correct to me.