610 lines
26 KiB
Markdown
610 lines
26 KiB
Markdown
[algorithms.parallel]
|
||
|
||
# 26 Algorithms library [[algorithms]](./#algorithms)
|
||
|
||
## 26.3 Parallel algorithms [algorithms.parallel]
|
||
|
||
### [26.3.1](#defns) Preamble [[algorithms.parallel.defns]](algorithms.parallel.defns)
|
||
|
||
[1](#defns-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L287)
|
||
|
||
Subclause [algorithms.parallel] describes components that C++ programs may use
|
||
to perform operations on containers and other sequences in parallel[.](#defns-1.sentence-1)
|
||
|
||
[2](#defns-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L291)
|
||
|
||
A [*parallel algorithm*](#def:parallel_algorithm "26.3.1 Preamble [algorithms.parallel.defns]") is a function template listed in this document
|
||
with a template parameter named ExecutionPolicy or constrained by the following exposition-only concept:template<class Ep>concept [*execution-policy*](#concept:execution-policy "26.3.1 Preamble [algorithms.parallel.defns]") = is_execution_policy_v<remove_cvref_t<Ep>>; // *exposition only*
|
||
|
||
Such a template parameter is termed an [*execution policy template parameter*](#def:template_parameter,execution_policy "26.3.1 Preamble [algorithms.parallel.defns]")[.](#defns-2.sentence-2)
|
||
|
||
[3](#defns-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L301)
|
||
|
||
A parallel algorithm accesses objects indirectly accessible via its arguments
|
||
by invoking the following functions:
|
||
|
||
- [(3.1)](#defns-3.1)
|
||
|
||
All operations of the categories of the iterators, sentinels, or mdspan types
|
||
that the algorithm is instantiated with[.](#defns-3.1.sentence-1)
|
||
|
||
- [(3.2)](#defns-3.2)
|
||
|
||
Operations on those sequence elements that are required by its specification[.](#defns-3.2.sentence-1)
|
||
|
||
- [(3.3)](#defns-3.3)
|
||
|
||
User-provided invocable objects
|
||
to be applied during the execution of the algorithm,
|
||
if required by the specification[.](#defns-3.3.sentence-1)
|
||
|
||
- [(3.4)](#defns-3.4)
|
||
|
||
Operations on those invocable objects required by the specification[.](#defns-3.4.sentence-1)
|
||
[*Note [1](#defns-note-1)*:
|
||
See [[algorithms.requirements]](algorithms.requirements "26.2 Algorithms requirements")[.](#defns-3.4.sentence-2)
|
||
â *end note*]
|
||
|
||
These functions are herein called [*element access functions*](#def:element_access_functions "26.3.1 Preamble [algorithms.parallel.defns]")[.](#defns-3.sentence-2)
|
||
|
||
[4](#defns-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L322)
|
||
|
||
[*Example [1](#defns-example-1)*:
|
||
|
||
The sort function may invoke the following element access functions:
|
||
|
||
- [(4.1)](#defns-4.1)
|
||
|
||
Operations of the random-access iterator of the actual template argument
|
||
(as per [[random.access.iterators]](random.access.iterators "24.3.5.7 Random access iterators")),
|
||
as implied by the name of the template parameter RandomAccessIterator[.](#defns-4.1.sentence-1)
|
||
|
||
- [(4.2)](#defns-4.2)
|
||
|
||
The swap function on the elements of the sequence
|
||
(as per the preconditions specified in [[sort]](sort "26.8.2.1 sort"))[.](#defns-4.2.sentence-1)
|
||
|
||
- [(4.3)](#defns-4.3)
|
||
|
||
The user-provided Compare function object[.](#defns-4.3.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
[5](#defns-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L338)
|
||
|
||
A standard library function is [*vectorization-unsafe*](#def:vectorization-unsafe "26.3.1 Preamble [algorithms.parallel.defns]") if it is specified to synchronize with another function invocation, or
|
||
another function invocation is specified to synchronize with it,
|
||
and if it is not a memory allocation or deallocation function
|
||
or lock-free atomic modify-write operation ([[atomics.order]](atomics.order "32.5.4 Order and consistency"))[.](#defns-5.sentence-1)
|
||
|
||
[*Note [2](#defns-note-2)*:
|
||
|
||
Implementations must ensure that internal synchronization
|
||
inside standard library functions does not prevent forward progress
|
||
when those functions are executed by threads of execution
|
||
with weakly parallel forward progress guarantees[.](#defns-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#defns-example-2)*: int x = 0;
|
||
std::mutex m;void f() {int a[] = {1,2};
|
||
std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); // incorrect: lock_guard constructor calls m.lock()++x; });}
|
||
|
||
The above program may result in two consecutive calls to m.lock() on the same thread of execution (which may deadlock),
|
||
because the applications of the function object are not guaranteed
|
||
to run on different threads of execution[.](#defns-5.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
### [26.3.2](#user) Requirements on user-provided function objects [[algorithms.parallel.user]](algorithms.parallel.user)
|
||
|
||
[1](#user-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L370)
|
||
|
||
Unless otherwise specified,
|
||
invocable objects passed into parallel algorithms as objects of a type
|
||
denoted by a template parameter namedPredicate,BinaryPredicate,Compare,UnaryOperation,BinaryOperation,BinaryOperation1,BinaryOperation2,BinaryDivideOp, or
|
||
constrained by a concept that subsumes [regular_invocable](concept.regularinvocable#concept:regular_invocable "18.7.3 Concept regular_invocable [concept.regularinvocable]") and the operators used by the analogous overloads to these parallel algorithms
|
||
that are formed by an invocation
|
||
with the specified default predicate or operation (where applicable)
|
||
shall not directly or indirectly modify objects via their arguments,
|
||
nor shall they rely on the identity of the provided objects[.](#user-1.sentence-1)
|
||
|
||
### [26.3.3](#exec) Effect of execution policies on algorithm execution [[algorithms.parallel.exec]](algorithms.parallel.exec)
|
||
|
||
[1](#exec-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L391)
|
||
|
||
An execution policy template parameter describes
|
||
the manner in which the execution of a parallel algorithm may be
|
||
parallelized and the manner in which it applies the element access functions[.](#exec-1.sentence-1)
|
||
|
||
[2](#exec-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L396)
|
||
|
||
If an object is modified by an element access function,
|
||
the algorithm will perform no other unsynchronized accesses to that object[.](#exec-2.sentence-1)
|
||
|
||
The modifying element access functions are those
|
||
which are specified as modifying the object[.](#exec-2.sentence-2)
|
||
|
||
[*Note [1](#exec-note-1)*:
|
||
|
||
For example,swap,++,--,@=, and
|
||
assignments
|
||
modify the object[.](#exec-2.sentence-3)
|
||
|
||
For the assignment and @= operators, only the left argument is modified[.](#exec-2.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[3](#exec-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L412)
|
||
|
||
Unless otherwise stated, implementations may make arbitrary copies of elements
|
||
(with type T) from sequences
|
||
where is_trivially_copy_constructible_v<T> and is_trivially_destructible_v<T> are true[.](#exec-3.sentence-1)
|
||
|
||
[*Note [2](#exec-note-2)*:
|
||
|
||
This implies that user-supplied function objects cannot rely on
|
||
object identity of arguments for such input sequences[.](#exec-3.sentence-2)
|
||
|
||
If object identity of the arguments to these function objects
|
||
is important, a wrapping iterator
|
||
that returns a non-copied implementation object
|
||
such as reference_wrapper<T> ([[refwrap]](refwrap "22.10.6 Class template reference_wrapper")),
|
||
or some equivalent solution, can be used[.](#exec-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[4](#exec-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L427)
|
||
|
||
The invocations of element access functions in parallel algorithms invoked with
|
||
an execution policy object of type execution::sequenced_policy all occur
|
||
in the calling thread of execution[.](#exec-4.sentence-1)
|
||
|
||
[*Note [3](#exec-note-3)*:
|
||
|
||
The invocations are not interleaved; see [[intro.execution]](intro.execution "6.10.1 Sequential execution")[.](#exec-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[5](#exec-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L435)
|
||
|
||
The invocations of element access functions in parallel algorithms invoked with
|
||
an execution policy object of type execution::unsequenced_policy are permitted to execute in an unordered fashion
|
||
in the calling thread of execution,
|
||
unsequenced with respect to one another in the calling thread of execution[.](#exec-5.sentence-1)
|
||
|
||
[*Note [4](#exec-note-4)*:
|
||
|
||
This means that multiple function object invocations
|
||
can be interleaved on a single thread of execution,
|
||
which overrides the usual guarantee from [[intro.execution]](intro.execution "6.10.1 Sequential execution") that function executions do not overlap with one another[.](#exec-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
The behavior of a program is undefined if
|
||
it invokes a vectorization-unsafe standard library function
|
||
from user code
|
||
called from an execution::unsequenced_policy algorithm[.](#exec-5.sentence-3)
|
||
|
||
[*Note [5](#exec-note-5)*:
|
||
|
||
Because execution::unsequenced_policy allows
|
||
the execution of element access functions
|
||
to be interleaved on a single thread of execution,
|
||
blocking synchronization, including the use of mutexes, risks deadlock[.](#exec-5.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[6](#exec-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L458)
|
||
|
||
The invocations of element access functions in parallel algorithms invoked with
|
||
an execution policy object of type execution::parallel_policy are permitted to execute either
|
||
in the invoking thread of execution or
|
||
in a thread of execution implicitly created by the library
|
||
to support parallel algorithm execution[.](#exec-6.sentence-1)
|
||
|
||
If the threads of execution created by thread ([[thread.thread.class]](thread.thread.class "32.4.3 Class thread"))
|
||
or jthread ([[thread.jthread.class]](thread.jthread.class "32.4.4 Class jthread"))
|
||
provide concurrent forward progress guarantees ([[intro.progress]](intro.progress "6.10.2.3 Forward progress")),
|
||
then a thread of execution implicitly created by the library will provide
|
||
parallel forward progress guarantees;
|
||
otherwise, the provided forward progress guarantee isimplementation-defined[.](#exec-6.sentence-2)
|
||
|
||
Any such invocations executing in the same thread of execution
|
||
are indeterminately sequenced with respect to each other[.](#exec-6.sentence-3)
|
||
|
||
[*Note [6](#exec-note-6)*:
|
||
|
||
It is the caller's responsibility to ensure
|
||
that the invocation does not introduce data races or deadlocks[.](#exec-6.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#exec-example-1)*: int a[] = {0,1};
|
||
std::vector<int> v;
|
||
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int i) { v.push_back(i*2+1); // incorrect: data race});
|
||
|
||
The program above has a data race because of the unsynchronized access to the
|
||
container v[.](#exec-6.sentence-5)
|
||
|
||
â *end example*]
|
||
|
||
[*Example [2](#exec-example-2)*: std::atomic<int> x{0};int a[] = {1,2};
|
||
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { x.fetch_add(1, std::memory_order::relaxed); // spin wait for another iteration to change the value of xwhile (x.load(std::memory_order::relaxed) == 1) { } // incorrect: assumes execution order});
|
||
|
||
The above example depends on the order of execution of the iterations, and
|
||
will not terminate if both iterations are executed sequentially
|
||
on the same thread of execution[.](#exec-6.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
[*Example [3](#exec-example-3)*: int x = 0;
|
||
std::mutex m;int a[] = {1,2};
|
||
std::for_each(std::execution::par, std::begin(a), std::end(a), [&](int) { std::lock_guard<mutex> guard(m); ++x;});
|
||
|
||
The above example synchronizes access to object x ensuring that it is incremented correctly[.](#exec-6.sentence-7)
|
||
|
||
â *end example*]
|
||
|
||
[7](#exec-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L518)
|
||
|
||
The invocations of element access functions in parallel algorithms invoked with
|
||
an execution policy object of type execution::parallel_unsequenced_policy are
|
||
permitted to execute
|
||
in an unordered fashion in unspecified threads of execution, and
|
||
unsequenced with respect to one another within each thread of execution[.](#exec-7.sentence-1)
|
||
|
||
These threads of execution are
|
||
either the invoking thread of execution
|
||
or threads of execution implicitly created by the library;
|
||
the latter will provide weakly parallel forward progress guarantees[.](#exec-7.sentence-2)
|
||
|
||
[*Note [7](#exec-note-7)*:
|
||
|
||
This means that multiple function object invocations can be interleaved
|
||
on a single thread of execution,
|
||
which overrides the usual guarantee from [[intro.execution]](intro.execution "6.10.1 Sequential execution") that function executions do not overlap with one another[.](#exec-7.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
The behavior of a program is undefined if
|
||
it invokes a vectorization-unsafe standard library function
|
||
from user code
|
||
called from an execution::parallel_unsequenced_policy algorithm[.](#exec-7.sentence-4)
|
||
|
||
[*Note [8](#exec-note-8)*:
|
||
|
||
Because execution::parallel_unsequenced_policy allows
|
||
the execution of element access functions
|
||
to be interleaved on a single thread of execution,
|
||
blocking synchronization, including the use of mutexes, risks deadlock[.](#exec-7.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[8](#exec-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L545)
|
||
|
||
[*Note [9](#exec-note-9)*:
|
||
|
||
The semantics of invocation withexecution::unsequenced_policy,execution::parallel_policy, orexecution::parallel_unsequenced_policy allow the implementation to fall back to sequential execution
|
||
if the system cannot parallelize an algorithm invocation,
|
||
e.g., due to lack of resources[.](#exec-8.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[9](#exec-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L556)
|
||
|
||
If an invocation of a parallel algorithm uses threads of execution
|
||
implicitly created by the library,
|
||
then the invoking thread of execution will either
|
||
|
||
- [(9.1)](#exec-9.1)
|
||
|
||
temporarily block
|
||
with forward progress guarantee delegation ([[intro.progress]](intro.progress "6.10.2.3 Forward progress"))
|
||
on the completion of these library-managed threads of execution, or
|
||
|
||
- [(9.2)](#exec-9.2)
|
||
|
||
eventually execute an element access function;
|
||
|
||
the thread of execution will continue to do so until the algorithm is finished[.](#exec-9.sentence-1)
|
||
|
||
[*Note [10](#exec-note-10)*:
|
||
|
||
In blocking with forward progress guarantee delegation in this context,
|
||
a thread of execution created by the library
|
||
is considered to have finished execution
|
||
as soon as it has finished the execution
|
||
of the particular element access function
|
||
that the invoking thread of execution logically depends on[.](#exec-9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[10](#exec-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L578)
|
||
|
||
The semantics of parallel algorithms invoked with an execution policy object ofimplementation-defined type
|
||
are implementation-defined[.](#exec-10.sentence-1)
|
||
|
||
### [26.3.4](#exceptions) Parallel algorithm exceptions [[algorithms.parallel.exceptions]](algorithms.parallel.exceptions)
|
||
|
||
[1](#exceptions-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L586)
|
||
|
||
During the execution of a parallel algorithm,
|
||
if temporary memory resources are required for parallelization
|
||
and none are available, the algorithm throws a bad_alloc exception[.](#exceptions-1.sentence-1)
|
||
|
||
[2](#exceptions-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L591)
|
||
|
||
During the execution of a parallel algorithm,
|
||
if the invocation of an element access function exits via an uncaught exception,
|
||
the behavior is determined by the execution policy[.](#exceptions-2.sentence-1)
|
||
|
||
### [26.3.5](#overloads) Parallel algorithm overloads [[algorithms.parallel.overloads]](algorithms.parallel.overloads)
|
||
|
||
[1](#overloads-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L598)
|
||
|
||
Parallel algorithms are algorithm overloads[.](#overloads-1.sentence-1)
|
||
|
||
Each parallel algorithm overload
|
||
has an additional function parameter P of type T&& as the first function parameter,
|
||
where T is the execution policy template parameter[.](#overloads-1.sentence-2)
|
||
|
||
[*Note [1](#overloads-note-1)*:
|
||
|
||
Not all algorithms have parallel algorithm overloads[.](#overloads-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[2](#overloads-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L608)
|
||
|
||
Unless otherwise specified,
|
||
the semantics of calling a parallel algorithm overload are identical to
|
||
calling the corresponding algorithm overload without the parameter P,
|
||
using all but the first argument[.](#overloads-2.sentence-1)
|
||
|
||
[3](#overloads-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L614)
|
||
|
||
Unless otherwise specified,
|
||
the complexity requirements of a parallel algorithm overload
|
||
are relaxed from the complexity requirements of the corresponding overload
|
||
without the parameter P as follows:
|
||
when the guarantee says âat most *expr*â or
|
||
âexactly *expr*â
|
||
and does not specify the number of assignments or swaps, and*expr* is not already expressed with O() notation,
|
||
the complexity of the algorithm shall be O(expr)[.](#overloads-3.sentence-1)
|
||
|
||
[4](#overloads-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L626)
|
||
|
||
A parallel algorithm
|
||
with a template parameter named ExecutionPolicy shall not participate in overload resolution unless
|
||
that template parameter satisfies [*execution-policy*](#concept:execution-policy "26.3.1 Preamble [algorithms.parallel.defns]")[.](#overloads-4.sentence-1)
|
||
|
||
### [26.3.6](#execpol) Execution policies [[execpol]](execpol)
|
||
|
||
#### [26.3.6.1](#execpol.general) General [[execpol.general]](execpol.general)
|
||
|
||
[1](#execpol.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L636)
|
||
|
||
Subclause [[execpol]](#execpol "26.3.6 Execution policies") describes classes that are [*execution policy*](#def:execution_policy "26.3.6.1 General [execpol.general]") types[.](#execpol.general-1.sentence-1)
|
||
|
||
An
|
||
object of an execution policy type indicates the kinds of parallelism allowed
|
||
in the execution of an algorithm and expresses the consequent requirements on
|
||
the element access functions[.](#execpol.general-1.sentence-2)
|
||
|
||
Execution policy types are declared in header [<execution>](execution.syn#header:%3cexecution%3e "33.4 Header <execution> synopsis [execution.syn]")[.](#execpol.general-1.sentence-3)
|
||
|
||
[*Example [1](#execpol.general-example-1)*: using namespace std;
|
||
vector<int> v = /* ... */;
|
||
|
||
// standard sequential sort sort(v.begin(), v.end());
|
||
|
||
// explicitly sequential sort sort(execution::seq, v.begin(), v.end());
|
||
|
||
// permitting parallel execution sort(execution::par, v.begin(), v.end());
|
||
|
||
// permitting vectorization as well sort(execution::par_unseq, v.begin(), v.end()); â *end example*]
|
||
|
||
[*Note [1](#execpol.general-note-1)*:
|
||
|
||
Implementations can provide additional execution policies
|
||
to those described in this document as extensions
|
||
to address parallel architectures that require idiosyncratic
|
||
parameters for efficient execution[.](#execpol.general-1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
#### [26.3.6.2](#execpol.type) Execution policy type trait [[execpol.type]](execpol.type)
|
||
|
||
[ð](#lib:is_execution_policy)
|
||
|
||
`template<class T> struct is_execution_policy;
|
||
`
|
||
|
||
[1](#execpol.type-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L675)
|
||
|
||
is_execution_policy can be used to detect execution policies for the
|
||
purpose of excluding function signatures from otherwise ambiguous overload
|
||
resolution participation[.](#execpol.type-1.sentence-1)
|
||
|
||
[2](#execpol.type-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L680)
|
||
|
||
is_execution_policy<T> is a *Cpp17UnaryTypeTrait* with a
|
||
base characteristic of true_type if T is the type of a standard
|
||
or implementation-defined
|
||
execution policy, otherwise false_type[.](#execpol.type-2.sentence-1)
|
||
|
||
[*Note [1](#execpol.type-note-1)*:
|
||
|
||
This provision reserves the privilege of creating non-standard execution
|
||
policies to the library implementation[.](#execpol.type-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[3](#execpol.type-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L691)
|
||
|
||
The behavior of a program that adds specializations foris_execution_policy is undefined[.](#execpol.type-3.sentence-1)
|
||
|
||
#### [26.3.6.3](#execpol.seq) Sequenced execution policy [[execpol.seq]](execpol.seq)
|
||
|
||
[ð](#lib:execution::sequenced_policy)
|
||
|
||
`class execution::sequenced_policy { unspecified };
|
||
`
|
||
|
||
[1](#execpol.seq-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L704)
|
||
|
||
The class execution::sequenced_policy is an execution policy type used
|
||
as a unique type to disambiguate parallel algorithm overloading and require
|
||
that a parallel algorithm's execution may not be parallelized[.](#execpol.seq-1.sentence-1)
|
||
|
||
[2](#execpol.seq-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L709)
|
||
|
||
During the execution of a parallel algorithm with
|
||
the execution::sequenced_policy policy,
|
||
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#execpol.seq-2.sentence-1)
|
||
|
||
#### [26.3.6.4](#execpol.par) Parallel execution policy [[execpol.par]](execpol.par)
|
||
|
||
[ð](#lib:execution::parallel_policy)
|
||
|
||
`class execution::parallel_policy { unspecified };
|
||
`
|
||
|
||
[1](#execpol.par-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L724)
|
||
|
||
The class execution::parallel_policy is an execution policy type used as
|
||
a unique type to disambiguate parallel algorithm overloading and indicate that
|
||
a parallel algorithm's execution may be parallelized[.](#execpol.par-1.sentence-1)
|
||
|
||
[2](#execpol.par-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L729)
|
||
|
||
During the execution of a parallel algorithm with
|
||
the execution::parallel_policy policy,
|
||
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#execpol.par-2.sentence-1)
|
||
|
||
#### [26.3.6.5](#execpol.parunseq) Parallel and unsequenced execution policy [[execpol.parunseq]](execpol.parunseq)
|
||
|
||
[ð](#lib:execution::parallel_unsequenced_policy)
|
||
|
||
`class execution::parallel_unsequenced_policy { unspecified };
|
||
`
|
||
|
||
[1](#execpol.parunseq-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L744)
|
||
|
||
The class execution::parallel_unsequenced_policy is an execution policy type
|
||
used as a unique type to disambiguate parallel algorithm overloading and
|
||
indicate that a parallel algorithm's execution may be parallelized and
|
||
vectorized[.](#execpol.parunseq-1.sentence-1)
|
||
|
||
[2](#execpol.parunseq-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L750)
|
||
|
||
During the execution of a parallel algorithm with
|
||
the execution::parallel_unsequenced_policy policy,
|
||
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#execpol.parunseq-2.sentence-1)
|
||
|
||
#### [26.3.6.6](#execpol.unseq) Unsequenced execution policy [[execpol.unseq]](execpol.unseq)
|
||
|
||
[ð](#lib:execution::unsequenced_policy)
|
||
|
||
`class execution::unsequenced_policy { unspecified };
|
||
`
|
||
|
||
[1](#execpol.unseq-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L765)
|
||
|
||
The class unsequenced_policy is an execution policy type
|
||
used as a unique type to disambiguate parallel algorithm overloading and
|
||
indicate that a parallel algorithm's execution may be vectorized,
|
||
e.g., executed on a single thread using instructions
|
||
that operate on multiple data items[.](#execpol.unseq-1.sentence-1)
|
||
|
||
[2](#execpol.unseq-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L772)
|
||
|
||
During the execution of a parallel algorithm with
|
||
the execution::unsequenced_policy policy,
|
||
if the invocation of an element access function exits via an exception,terminate is invoked ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#execpol.unseq-2.sentence-1)
|
||
|
||
#### [26.3.6.7](#execpol.objects) Execution policy objects [[execpol.objects]](execpol.objects)
|
||
|
||
[ð](#lib:seq)
|
||
|
||
`inline constexpr execution::sequenced_policy execution::seq{ unspecified };
|
||
inline constexpr execution::parallel_policy execution::par{ unspecified };
|
||
inline constexpr execution::parallel_unsequenced_policy execution::par_unseq{ unspecified };
|
||
inline constexpr execution::unsequenced_policy execution::unseq{ unspecified };
|
||
`
|
||
|
||
[1](#execpol.objects-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L795)
|
||
|
||
The header [<execution>](execution.syn#header:%3cexecution%3e "33.4 Header <execution> synopsis [execution.syn]") declares global objects associated with each type of execution policy[.](#execpol.objects-1.sentence-1)
|