This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
[algorithms.parallel.defns]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#defns)
### 26.3.1 Preamble [algorithms.parallel.defns]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L287)
Subclause [[algorithms.parallel]](algorithms.parallel "26.3Parallel algorithms") describes components that C++ programs may use
to perform operations on containers and other sequences in parallel[.](#1.sentence-1)
[2](#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]")[.](#2.sentence-2)
[3](#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)](#3.1)
All operations of the categories of the iterators, sentinels, or mdspan types
that the algorithm is instantiated with[.](#3.1.sentence-1)
- [(3.2)](#3.2)
Operations on those sequence elements that are required by its specification[.](#3.2.sentence-1)
- [(3.3)](#3.3)
User-provided invocable objects
to be applied during the execution of the algorithm,
if required by the specification[.](#3.3.sentence-1)
- [(3.4)](#3.4)
Operations on those invocable objects required by the specification[.](#3.4.sentence-1)
[*Note [1](#note-1)*:
See [[algorithms.requirements]](algorithms.requirements "26.2Algorithms requirements")[.](#3.4.sentence-2)
— *end note*]
These functions are herein called [*element access functions*](#def:element_access_functions "26.3.1Preamble[algorithms.parallel.defns]")[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L322)
[*Example [1](#example-1)*:
The sort function may invoke the following element access functions:
- [(4.1)](#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[.](#4.1.sentence-1)
- [(4.2)](#4.2)
The swap function on the elements of the sequence
(as per the preconditions specified in [[sort]](sort "26.8.2.1sort"))[.](#4.2.sentence-1)
- [(4.3)](#4.3)
The user-provided Compare function object[.](#4.3.sentence-1)
— *end example*]
[5](#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"))[.](#5.sentence-1)
[*Note [2](#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[.](#5.sentence-2)
— *end note*]
[*Example [2](#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[.](#5.sentence-3)
— *end example*]

View File

@@ -0,0 +1,23 @@
[algorithms.parallel.exceptions]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#exceptions)
### 26.3.4 Parallel algorithm exceptions [algorithms.parallel.exceptions]
[1](#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[.](#1.sentence-1)
[2](#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[.](#2.sentence-1)

View File

@@ -0,0 +1,241 @@
[algorithms.parallel.exec]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#exec)
### 26.3.3 Effect of execution policies on algorithm execution [algorithms.parallel.exec]
[1](#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[.](#1.sentence-1)
[2](#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[.](#2.sentence-1)
The modifying element access functions are those
which are specified as modifying the object[.](#2.sentence-2)
[*Note [1](#note-1)*:
For example,swap,++,--,@=, and
assignments
modify the object[.](#2.sentence-3)
For the assignment and @= operators, only the left argument is modified[.](#2.sentence-4)
— *end note*]
[3](#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[.](#3.sentence-1)
[*Note [2](#note-2)*:
This implies that user-supplied function objects cannot rely on
object identity of arguments for such input sequences[.](#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[.](#3.sentence-3)
— *end note*]
[4](#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[.](#4.sentence-1)
[*Note [3](#note-3)*:
The invocations are not interleaved; see [[intro.execution]](intro.execution "6.10.1Sequential execution")[.](#4.sentence-2)
— *end note*]
[5](#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[.](#5.sentence-1)
[*Note [4](#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[.](#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[.](#5.sentence-3)
[*Note [5](#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[.](#5.sentence-4)
— *end note*]
[6](#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[.](#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[.](#6.sentence-2)
Any such invocations executing in the same thread of execution
are indeterminately sequenced with respect to each other[.](#6.sentence-3)
[*Note [6](#note-6)*:
It is the caller's responsibility to ensure
that the invocation does not introduce data races or deadlocks[.](#6.sentence-4)
— *end note*]
[*Example [1](#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[.](#6.sentence-5)
— *end example*]
[*Example [2](#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[.](#6.sentence-6)
— *end example*]
[*Example [3](#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[.](#6.sentence-7)
— *end example*]
[7](#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[.](#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[.](#7.sentence-2)
[*Note [7](#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[.](#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[.](#7.sentence-4)
[*Note [8](#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[.](#7.sentence-5)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L545)
[*Note [9](#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[.](#8.sentence-1)
— *end note*]
[9](#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)](#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)](#9.2)
eventually execute an element access function;
the thread of execution will continue to do so until the algorithm is finished[.](#9.sentence-1)
[*Note [10](#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[.](#9.sentence-2)
— *end note*]
[10](#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[.](#10.sentence-1)

View File

@@ -0,0 +1,53 @@
[algorithms.parallel.overloads]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#overloads)
### 26.3.5 Parallel algorithm overloads [algorithms.parallel.overloads]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/algorithms.tex#L598)
Parallel algorithms are algorithm 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[.](#1.sentence-2)
[*Note [1](#note-1)*:
Not all algorithms have parallel algorithm overloads[.](#1.sentence-3)
— *end note*]
[2](#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[.](#2.sentence-1)
[3](#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)[.](#3.sentence-1)
[4](#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*](algorithms.parallel.defns#concept:execution-policy "26.3.1Preamble[algorithms.parallel.defns]")[.](#4.sentence-1)

View File

@@ -0,0 +1,20 @@
[algorithms.parallel.user]
# 26 Algorithms library [[algorithms]](./#algorithms)
## 26.3 Parallel algorithms [[algorithms.parallel]](algorithms.parallel#user)
### 26.3.2 Requirements on user-provided function objects [algorithms.parallel.user]
[1](#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[.](#1.sentence-1)