I was told that I could use Grand Central Dispatch to run n processes simultaneously, in an asynchronous fashion. The documentation said that if the processes were in a for loop, I could use the function dispatch_apply. But now it's saying
Note that dispatch_apply is synchronous, so all the applied blocks will have completed by the time it returns.
Does this mean the blocks that are submitted to a queue using dispatch_apply are executed in order? If so, what is the point of using concurrency? Won't the slowdown be the same?
dispatch_apply
is, as stated in the docs, synchronous. It runs a block on the specified queue in parallel (if possible) and waits until all the blocks return. If you want to run a block just once asynchronously, use dispatch_async
, if you want to run a block multiple times in parallel without blocking your current queue, just call dispatch_apply
within dispatch_async
:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(size_t size) {
NSLog(@"%lu", size);
});
});
The purpose of the synchronous dispatch_apply
is to asynchronously dispatch the inner loop interations to available parallel processing resources. Thus, the overall loop performance may speed up.
Faster loop performance? Very possibly, Yes. (see caveat)
Blocks the thread calling dispatch_apply
? Yes, just like loop blocks until completed.
For GCD, dispatch_apply
is synchronous since dispatch_apply
will not return until all the asynchronous, parallel tasks that dispatch_apply
creates have completed.
However, each individual task enqueued by dispatch_apply
can run as concurrent asynchronous tasks if the target queue
is asynchronous.
For example in Swift:
let batchCount: Int = 10
let queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
dispatch_apply(batchCount, queue) {
(i: Int) -> Void in
print(i, terminator: " ")
}
print("\ndispatch_apply QOS_CLASS_UTILITY queue completed")
yields unordered output like:
0 8 1 9 2 3 4 5 6 7
dispatch_apply QOS_CLASS_UTILITY queue completed
So, dispatch_apply
synchronously blocks when called, but the "batch" of tasks generated by dispatch_apply
can run concurrently, asynchronously, in parallel to each other.
Keep in mind the caveat that ...
the work performed during each iteration is distinct from the work performed during all other iterations, and the order in which each successive loop finished is unimportant
Also, note that use of a serial queue for the inner loop tasks will not have any performance gain.
Although using a serial queue is permissible and does the right thing for your code, using such a queue has no real performance advantages over leaving the loop in place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With