Module std.parallelism
std.parallelism
implements high-level primitives for SMP parallelism.
These include parallel
foreach, parallel
reduce, parallel
eager map, pipelining
and future/promise parallelism. std.parallelism
is recommended when the
same operation is to be executed in parallel
on different data, or when a
function is to be executed in a background thread and its result returned to a
well-defined main thread. For communication between arbitrary threads, see
.
std.concurrency
std.parallelism
is based on the concept of a
. A Task
is an
Task
object
that represents the fundamental unit of work in this library and may be
executed in parallel
with any other
. Using Task
directly allows programming with a future/promise paradigm. All other
supported parallelism paradigms (Task
parallel
foreach, map, reduce, pipelining)
represent an additional level of abstraction over
. They
automatically create one or more Task
objects, or closely related types
that are conceptually identical but not part of the public API.
Task
After creation, a
may be executed in a new thread, or submitted
to a Task
for execution. A TaskPool
encapsulates a TaskPool
task
queue
and its worker threads. Its purpose is to efficiently map a large
number of
s onto a smaller number of threads. A Task
task
queue is a
FIFO queue of
objects that have been submitted to the
Task
and are awaiting execution. A worker thread is a thread that
is associated with exactly one TaskPool
task
queue. It executes the
at the
front of its queue when the queue has work available, or sleeps when
no work is available. Each Task
task
queue is associated with zero or
more worker threads. If the result of a
is needed before execution
by a worker thread has begun, the Task
can be removed from the Task
task
queue
and executed immediately in the thread where the result is needed.
Warning
Unless marked as @trusted
or @safe
, artifacts in
this module allow implicit data sharing between threads and cannot
guarantee that client code is free from low level data races.
Synopsis
import std.algorithm, std.parallelism, std.range; void main() { // Parallel reduce can be combined with // std.algorithm.map to interesting effect. // The following example (thanks to Russel Winder) // calculates pi by quadrature using // std.algorithm.map and TaskPool.reduce. // getTerm is evaluated in parallel as needed by // TaskPool.reduce. // // Timings on an Athlon 64 X2 dual core machine: // // TaskPool.reduce: 12.170 s // std.algorithm.reduce: 24.065 s immutable n = 1_000_000_000; immutable delta = 1.0 / n; real getTerm(int i) { immutable x = ( i - 0.5 ) * delta; return delta / ( 1.0 + x * x ) ; } immutable pi = 4.0 * taskPool.reduce!"a + b"( std.algorithm.map!getTerm(iota(n)) ); }
Author
David Simcha
Functions
Name | Description |
---|---|
defaultPoolThreads
|
These properties get and set the number of worker threads in the
instance returned by . The default value is - 1.
Calling the setter after the first call to does not changes
number of worker threads in the instance returned by .
|
parallel
|
Convenience functions that forwards to taskPool.parallel . The
purpose of these is to make parallel foreach less verbose and more
readable.
|
scopedTask
|
These functions allow the creation of objects on the stack rather
than the GC heap. The lifetime of a created by
cannot exceed the lifetime of the scope it was created in.
|
task
|
Creates a on the GC heap that calls an alias. This may be executed
via or by submitting to a
std.parallelism.TaskPool . A globally accessible instance of
is provided by std.parallelism.taskPool .
|
task
|
Creates a on the GC heap that calls a function pointer, delegate, or
class/struct with overloaded opCall.
|
task
|
Version of usable from @safe code. Usage mechanics are
identical to the non-@safe case, but safety introduces some restrictions:
|
taskPool
|
Returns a lazily initialized global instantiation of .
This function can safely be called concurrently from multiple non-worker
threads. The worker threads in this pool are daemon threads, meaning that it
is not necessary to call or before
terminating the main thread.
|
Classes
Name | Description |
---|---|
TaskPool
|
This class encapsulates a task queue and a set of worker threads. Its purpose
is to efficiently map a large number of s onto a smaller number of
threads. A task queue is a FIFO queue of objects that have been
submitted to the and are awaiting execution. A worker thread is a
thread that executes the at the front of the queue when one is
available and sleeps when the queue is empty.
|
Structs
Name | Description |
---|---|
Task
|
represents the fundamental unit of work. A may be
executed in parallel with any other . Using this struct directly
allows future/promise parallelism. In this paradigm, a function (or delegate
or other callable) is executed in a thread other than the one it was called
from. The calling thread does not block while the function is being executed.
A call to , , or is used to
ensure that the has finished executing and to obtain the return
value, if any. These functions and also act as full memory barriers,
meaning that any memory writes made in the thread that executed the
are guaranteed to be visible in the calling thread after one of these functions
returns.
|
Global variables
Name | Type | Description |
---|---|---|
totalCPUs
|
immutable(uint)
|
The total number of CPU cores available on the current machine, as reported by the operating system. |