std::execution:: sequenced_policy, std::execution:: parallel_policy, std::execution:: parallel_unsequenced_policy, std::execution:: unsequenced_policy
|
Definido en el encabezado
<execution>
|
||
|
class
sequenced_policy
{
/* no especificado */
}
;
|
(1) | (desde C++17) |
|
class
parallel_policy
{
/* no especificado */
}
;
|
(2) | (desde C++17) |
|
class
parallel_unsequenced_policy
{
/* no especificado */
}
;
|
(3) | (desde C++17) |
|
class
unsequenced_policy
{
/* no especificado */
}
;
|
(4) | (desde C++20) |
Durante la ejecución de un algoritmo paralelo con cualquiera de estas políticas de ejecución, si la invocación de una función de acceso a elementos finaliza mediante una excepción no capturada, std::terminate es llamado, pero las implementaciones pueden definir políticas de ejecución adicionales que manejen las excepciones de manera diferente.
Notas
Al utilizar la política de ejecución en paralelo, es responsabilidad del programador evitar las condiciones de carrera y los bloqueos mutuos:
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: carrera de datos });
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: asume el orden de ejecución });
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; // correcto });
Las políticas de ejecución no secuenciadas son el único caso donde las llamadas a funciones están no secuenciadas entre sí, lo que significa que pueden entrelazarse. En todas las demás situaciones en C++, están indeterminadamente secuenciadas (no pueden entrelazarse). Debido a esto, los usuarios no pueden asignar o liberar memoria, adquirir mutexes, usar especializaciones no lock-free de std::atomic o, en general, realizar cualquier operación no segura para vectorización cuando usan estas políticas (las funciones no seguras para vectorización son aquellas que se sincronizan con otra función, por ejemplo std::mutex::unlock se sincroniza con la siguiente 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: el constructor de lock_guard llama a m.lock() ++x; });
Si la implementación no puede paralelizar o vectorizar (por ejemplo, debido a la falta de recursos), todas las políticas de ejecución estándar pueden recurrir a la ejecución secuencial.
Véase también
|
(C++17)
(C++17)
(C++17)
(C++20)
|
objetos globales de políticas de ejecución
(constante) |