Files
2025-10-25 03:02:53 +03:00

610 lines
26 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.1Preamble[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.1Preamble[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.1Preamble[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.2Algorithms requirements")[.](#defns-3.4.sentence-2)
— *end note*]
These functions are herein called [*element access functions*](#def:element_access_functions "26.3.1Preamble[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.7Random 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.1sort"))[.](#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.1Preamble[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.4Order 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.3Concept 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.6Class 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.1Sequential 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.1Sequential 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.3Class thread"))
or jthread ([[thread.jthread.class]](thread.jthread.class "32.4.4Class jthread"))
provide concurrent forward progress guarantees ([[intro.progress]](intro.progress "6.10.2.3Forward 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.1Sequential 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.3Forward 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.1Preamble[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.6Execution policies") describes classes that are [*execution policy*](#def:execution_policy "26.3.6.1General[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.4Header <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.2The 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.2The 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.2The 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.2The 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.4Header <execution> synopsis[execution.syn]") declares global objects associated with each type of execution policy[.](#execpol.objects-1.sentence-1)