Process Array in parallel using GCD
You can also use concurrentPerform(iterations: Int, execute work: (Int) -> Swift.Void)
(since Swift 3).
It has a much simpler syntax and will wait for all threads to finalise before returning.:
DispatchQueue.concurrentPerform(iterations: iterations) { i in
performOperation(i)
}
When you use the +=
operator, the LHS is an inout
parameter -- I think you're getting race conditions when, as you mention in your update, Swift moves around the array for optimization. I was able to get it to work by summing the chunk in a local variable, then simply assigning to the right index in summary
:
func calcSummary() {
let group = dispatch_group_create()
let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
for i in 0 ..< 10 {
dispatch_group_async(group, queue, {
let base = i * 50000
var sum = 0
for x in base ..< base + 50000 {
sum += self.array[x]
}
self.summary[i] = sum
})
}
dispatch_group_notify(group, queue, {
println(self.summary)
})
}
This is a slightly different take on the approach in @Eduardo's answer, using the Array
type's withUnsafeMutableBufferPointer<R>(body: (inout UnsafeMutableBufferPointer<T>) -> R) -> R
method. That method's documentation states:
Call
body(p)
, wherep
is a pointer to theArray
's mutable contiguous storage. If no such storage exists, it is first created.Often, the optimizer can eliminate bounds- and uniqueness-checks within an array algorithm, but when that fails, invoking the same algorithm on
body
's argument lets you trade safety for speed.
That second paragraph seems to be exactly what's happening here, so using this method might be more "idiomatic" in Swift, whatever that means:
func calcSummary() {
let group = dispatch_group_create()
let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
self.summary.withUnsafeMutableBufferPointer {
summaryMem -> Void in
for i in 0 ..< 10 {
dispatch_group_async(group, queue, {
let base = i * 50000
for x in base ..< base + 50000 {
summaryMem[i] += self.array[x]
}
})
}
}
dispatch_group_notify(group, queue, {
println(self.summary)
})
}