std::execution:: sequenced_policy, std::execution:: parallel_policy, std::execution:: parallel_unsequenced_policy, std::execution:: unsequenced_policy
From cppreference.net
C++
Algorithm library
|
定义于头文件
<execution>
|
||
|
class
sequenced_policy
{
/* 未指定 */
}
;
|
(1) | (C++17 起) |
|
class
parallel_policy
{
/* 未指定 */
}
;
|
(2) | (C++17 起) |
|
class
parallel_unsequenced_policy
{
/* 未指定 */
}
;
|
(3) | (C++17 起) |
|
class
unsequenced_policy
{
/* 未指定 */
}
;
|
(4) | (C++20 起) |
1)
用作唯一类型以消除并行算法重载歧义的执行策略类型,要求并行算法的执行不能被并行化。使用此策略(通常指定为
std::execution::seq
)调用的并行算法中的元素访问函数调用,在调用线程中以不确定顺序执行。
2)
用作唯一类型以消除并行算法重载歧义,并指示并行算法的执行可被并行化的执行策略类型。使用此策略(通常指定为
std::execution::par
)调用的并行算法中,元素访问函数的调用允许在执行线程或库隐式创建的用于支持并行算法执行的线程中执行。在同一线程中执行的此类调用彼此之间以不确定顺序排序。若由
std::thread
或
std::jthread
创建的执行线程提供并发前向进度保证,则库创建的执行线程提供并行前向进度保证。否则,提供的前向进度保证由实现定义。注:并行前向进度保证若某执行线程执行一步操作,其最终将执行另一步操作,这使得线程能够进入临界区并获取锁,因为持有锁的线程最终将被重新调度并能够释放该锁。
3)
用作唯一类型以消除并行算法重载歧义,并指示并行算法执行可能被并行化、向量化或在线程间迁移(例如通过工作窃取调度器)的执行策略类型。使用此策略调用的并行算法中,元素访问函数的调用允许在未指定线程中以无序方式执行,且在单个线程内彼此间无顺序关系。使用此策略调用的并行算法中,元素访问函数的调用不允许调用向量化不安全操作,例如标准库中规定的同步操作,包括
std::atomic
和其他并发原语的操作。若由
std::thread
或
std::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); // 错误:数据竞争 });
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) { } // 错误:假设了执行顺序 });
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; // 正确 });
非顺序执行策略是函数调用彼此间 非顺序 执行的唯一情形,这意味着它们可以交错执行。在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); // 错误:lock_guard 构造函数会调用 m.lock() ++x; });
如果实现无法并行化或向量化(例如由于资源不足),所有标准执行策略都可以回退到顺序执行。
参见
|
(C++17)
(C++17)
(C++17)
(C++20)
|
全局执行策略对象
(常量) |