命名空间
变体
操作

std::execution::sequenced_policy, std::execution::parallel_policy, std::execution::parallel_unsequenced_policy, std::execution::unsequenced_policy

来自 cppreference.cn
< cpp‎ | algorithm
 
 
算法库
约束算法和范围上的算法 (C++20)
约束算法,例如 ranges::copy, ranges::sort, ...
执行策略 (C++17)
execution::sequenced_policyexecution::parallel_policyexecution::parallel_unsequenced_policyexecution::parallel_unsequenced
(C++17)(C++17)(C++17)(C++20)
排序及相关操作
划分操作
排序操作
二分搜索操作
(在已划分范围上)
集合操作 (在已排序范围上)
合并操作 (在已排序范围上)
堆操作
最小/最大操作
(C++11)
(C++17)
字典序比较操作
排列操作
C 库
数值操作
未初始化内存上的操作
 
定义于头文件 <execution>
class sequenced_policy { /* unspecified */ };
(1) (自 C++17 起)
class parallel_policy { /* unspecified */ };
(2) (自 C++17 起)
class parallel_unsequenced_policy { /* unspecified */ };
(3) (自 C++17 起)
class unsequenced_policy { /* unspecified */ };
(4) (自 C++20 起)
1) 执行策略类型,用作唯一类型以消除并行算法重载的歧义,并要求并行算法的执行不能并行化。使用此策略(通常指定为 std::execution::seq)调用的并行算法中元素访问函数的调用在调用线程中以不确定顺序执行。
2) 执行策略类型,用作唯一类型以消除并行算法重载的歧义,并指示并行算法的执行可以并行化。使用此策略(通常指定为 std::execution::par)调用的并行算法中元素访问函数的调用,允许在调用线程或库隐式创建的线程中执行,以支持并行算法执行。在同一线程中执行的任何此类调用彼此之间以不确定顺序执行。如果 std::threadstd::jthread 创建的执行线程提供并发前向进度保证,则库创建的执行线程提供并行前向进度保证。否则,提供的前向进度保证是实现定义的。注意:并行前向进度保证,如果一个执行线程迈出一步,它最终会迈出另一步,从而使线程能够进入临界区并获取锁,因为拥有锁的线程最终将被再次调度并能够释放它。
3) 执行策略类型,用作唯一类型以消除并行算法重载的歧义,并指示并行算法的执行可以并行化、向量化或跨线程迁移(例如通过父窃取调度器)。使用此策略调用的并行算法中元素访问函数的调用,允许在未指定的线程中以无序方式执行,并且在每个线程内彼此无序。使用此策略调用的并行算法中元素访问函数的调用,不允许调用向量化不安全的操作,例如标准库指定的用于同步的操作,包括 std::atomic 和其他并发原语的操作。如果 std::threadstd::jthread 创建的执行线程提供并发前向进度保证,则库创建的执行线程提供弱并行前向进度保证。否则,提供的前向进度保证是调用并行算法的线程的前向进度保证。注意:弱并行前向进度保证,已经迈出一步的执行线程之一最终将迈出另一步,这不允许线程进入临界区或获取锁,因为拥有锁的线程可能不会被再次调度,直到尝试获取锁的线程退出。
4) 执行策略类型,用作唯一类型以消除并行算法重载的歧义,并指示并行算法的执行可以向量化,例如,在单线程上使用操作多个数据项的指令执行。

在使用任何这些执行策略执行并行算法期间,如果元素访问函数的调用通过未捕获的异常退出,则会调用 std::terminate,但实现可能会定义处理异常方式不同的其他执行策略。

[编辑] 注释

当使用并行执行策略时,程序员有责任避免数据竞争和死锁

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); // Error: data race
});
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);
    while (x.load(std::memory_order_relaxed) == 1) { } // Error: assumes execution order
});
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<std::mutex> guard(m);
    ++x; // correct
});

无序执行策略是函数调用彼此之间无序的唯一情况,这意味着它们可以交错执行。在 C++ 中的所有其他情况下,它们都是不确定顺序的(不能交错)。因此,当使用这些策略时,用户不允许分配或释放内存、获取互斥锁、使用非无锁 std::atomic 特化,或者通常执行任何向量化不安全的操作(向量化不安全的函数是指那些与另一个函数同步的函数,例如 std::mutex::unlock 与下一个 std::mutex::lock 同步)。

int x = 0;
std::mutex m;
int a[] = {1, 2};
std::for_each(std::execution::par_unseq, std::begin(a), std::end(a), [&](int)
{
    std::lock_guard<std::mutex> guard(m); // Error: lock_guard constructor calls m.lock()
    ++x;
});

如果实现无法并行化或向量化(例如,由于资源不足),所有标准执行策略都可以退回到顺序执行。

[编辑] 参见

(C++17)(C++17)(C++17)(C++20)
全局执行策略对象
(常量) [编辑]