| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- .\" Copyright (c) 2008-2017 Apple Inc. All rights reserved.
- .Dd May 1, 2009
- .Dt dispatch_apply 3
- .Os Darwin
- .Sh NAME
- .Nm dispatch_apply
- .Nd schedule blocks for iterative execution
- .Sh SYNOPSIS
- .Fd #include <dispatch/dispatch.h>
- .Ft void
- .Fo dispatch_apply
- .Fa "size_t iterations" "dispatch_queue_t queue" "void (^block)(size_t)"
- .Fc
- .Ft void
- .Fo dispatch_apply_f
- .Fa "size_t iterations" "dispatch_queue_t queue" "void *context" "void (*function)(void *, size_t)"
- .Fc
- .Sh DESCRIPTION
- The
- .Fn dispatch_apply
- function provides data-level concurrency through a "for (;;)" loop like primitive:
- .Bd -literal
- size_t iterations = 10;
- // 'idx' is zero indexed, just like:
- // for (idx = 0; idx < iterations; idx++)
- dispatch_apply(iterations, DISPATCH_APPLY_AUTO, ^(size_t idx) {
- printf("%zu\\n", idx);
- });
- .Ed
- .Pp
- Although any queue can be used, it is strongly recommended to use
- .Vt DISPATCH_APPLY_AUTO
- as the
- .Vt queue
- argument to both
- .Fn dispatch_apply
- and
- .Fn dispatch_apply_f ,
- as shown in the example above, since this allows the system to automatically use worker threads
- that match the configuration of the current thread as closely as possible.
- No assumptions should be made about which global concurrent queue will be used.
- .Pp
- Like a "for (;;)" loop, the
- .Fn dispatch_apply
- function is synchronous.
- If asynchronous behavior is desired, wrap the call to
- .Fn dispatch_apply
- with a call to
- .Fn dispatch_async
- against another queue.
- .Pp
- Sometimes, when the block passed to
- .Fn dispatch_apply
- is simple, the use of striding can tune performance.
- Calculating the optimal stride is best left to experimentation.
- Start with a stride of one and work upwards until the desired performance is
- achieved (perhaps using a power of two search):
- .Bd -literal
- #define STRIDE 3
- dispatch_apply(count / STRIDE, DISPATCH_APPLY_AUTO, ^(size_t idx) {
- size_t j = idx * STRIDE;
- size_t j_stop = j + STRIDE;
- do {
- printf("%zu\\n", j++);
- } while (j < j_stop);
- });
- size_t i;
- for (i = count - (count % STRIDE); i < count; i++) {
- printf("%zu\\n", i);
- }
- .Ed
- .Sh IMPLIED REFERENCES
- Synchronous functions within the dispatch framework hold an implied reference
- on the target queue. In other words, the synchronous function borrows the
- reference of the calling function (this is valid because the calling function
- is blocked waiting for the result of the synchronous function, and therefore
- cannot modify the reference count of the target queue until after the
- synchronous function has returned).
- .Pp
- This is in contrast to asynchronous functions which must retain both the block
- and target queue for the duration of the asynchronous operation (as the calling
- function may immediately release its interest in these objects).
- .Sh FUNDAMENTALS
- .Fn dispatch_apply
- and
- .Fn dispatch_apply_f
- attempt to quickly create enough worker threads to efficiently iterate work in parallel.
- By contrast, a loop that passes work items individually to
- .Fn dispatch_async
- or
- .Fn dispatch_async_f
- will incur more overhead and does not express the desired parallel execution semantics to
- the system, so may not create an optimal number of worker threads for a parallel workload.
- For this reason, prefer to use
- .Fn dispatch_apply
- or
- .Fn dispatch_apply_f
- when parallel execution is important.
- .Pp
- The
- .Fn dispatch_apply
- function is a wrapper around
- .Fn dispatch_apply_f .
- .Sh CAVEATS
- Unlike
- .Fn dispatch_async ,
- a block submitted to
- .Fn dispatch_apply
- is expected to be either independent or dependent
- .Em only
- on work already performed in lower-indexed invocations of the block. If
- the block's index dependency is non-linear, it is recommended to
- use a for-loop around invocations of
- .Fn dispatch_async .
- .Sh SEE ALSO
- .Xr dispatch 3 ,
- .Xr dispatch_async 3 ,
- .Xr dispatch_queue_create 3
|