Defined in header <execution> | ||
---|---|---|
class sequenced_policy { /* unspecified */ }; | (1) | (since C++17) |
class parallel_policy { /* unspecified */ }; | (2) | (since C++17) |
class parallel_unsequenced_policy { /* unspecified */ }; | (3) | (since C++17) |
std::execution::seq
) are indeterminately sequenced in the calling thread.std::execution::par
) are permitted to execute in either the invoking thread or in a thread implicitly created by the library to support parallel algorithm execution. Any such invocations executing in the same thread are indeterminately sequenced with respect to each other.During the execution of a parallel algorithm with any of these three execution policies, if the invocation of an element access function exits via an uncaught exception, std::terminate
is called, but the implementations may define additional execution policies that handle exceptions differently.
When using parallel execution policy, it is the programmer's responsibility to avoid deadlocks:
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 });
Unsequenced execution policy is the only case where function calls are unsequenced with respect to each other, meaning they can be interleaved. In all other situations in C++, they are indeterminately-sequenced (cannot interleave). Because of that, users are not allowed to allocate or deallocate memory, acquire mutexes, use non-lockfree std::atomic
specializations, or perform any other vectorization-unsafe operations when using this policy (vectorization-unsafe functions are the ones that synchronize-with another function, e.g. std::mutex::unlock
synchronizes-with the next 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) | global execution policy objects (constant) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t