Namespaces
Variants

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

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p.ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de modificación de secuencias
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Operaciones de ordenación y relacionadas
Operaciones de particionado
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de fusión (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
Definido en el encabezado <execution>
class sequenced_policy { /* unspecified */ };
(1) (desde C++17)
class parallel_policy { /* unspecified */ };
(2) (desde C++17)
class parallel_unsequenced_policy { /* unspecified */ };
(3) (desde C++17)
class unsequenced_policy { /* unspecified */ };
(4) (desde C++20)
1) El tipo de política de ejecución utilizado como tipo único para desambiguar la sobrecarga de algoritmos paralelos y requerir que la ejecución de un algoritmo paralelo no pueda ser paralelizada. Las invocaciones de las funciones de acceso a elementos en algoritmos paralelos invocados con esta política (normalmente especificada como std::execution::seq) están secuenciadas de forma indeterminada en el hilo llamante.
2) El tipo de política de ejecución utilizado como tipo único para desambiguar la sobrecarga de algoritmos paralelos e indicar que la ejecución de un algoritmo paralelo puede ser paralelizada. Las invocaciones de las funciones de acceso a elementos en algoritmos paralelos invocados con esta política (normalmente especificada como std::execution::par) pueden ejecutarse ya sea en el hilo invocante o en un hilo creado implícitamente por la biblioteca para soportar la ejecución de algoritmos paralelos. Cualquier invocación de este tipo que se ejecute en el mismo hilo está secuenciada de forma indeterminada con respecto a las demás. Si los hilos de ejecución creados por std::thread o std::jthread proporcionan garantías de progreso concurrente, entonces los hilos de ejecución creados por la biblioteca proporcionan garantías de progreso paralelo. De lo contrario, la garantía de progreso proporcionada está definida por la implementación. Nota: la garantía de progreso paralelo asegura que si un hilo de ejecución da un paso, eventualmente dará otro paso, permitiendo que los hilos entren en secciones críticas y tomen bloqueos, porque el hilo que tiene el bloqueo será eventualmente planificado nuevamente y podrá liberarlo.
3) El tipo de política de ejecución utilizado como tipo único para desambiguar la sobrecarga de algoritmos paralelos e indicar que la ejecución de un algoritmo paralelo puede ser paralelizada, vectorizada o migrada entre hilos (como por un planificador de robo de tareas padre). Las invocaciones de las funciones de acceso a elementos en algoritmos paralelos invocados con esta política pueden ejecutarse de manera desordenada en hilos no especificados, y sin secuencia con respecto a las demás dentro de cada hilo. Las invocaciones de las funciones de acceso a elementos en algoritmos paralelos invocados con esta política no pueden invocar operaciones no seguras para vectorización, como aquellas especificadas por la biblioteca estándar para sincronizar, incluyendo las de std::atomic y otras primitivas de concurrencia. Si los hilos de ejecución creados por std::thread o std::jthread proporcionan garantías de progreso concurrente, entonces los hilos de ejecución creados por la biblioteca proporcionan garantías de progreso débilmente paralelo. De lo contrario, la garantía de progreso proporcionada es la del hilo que invoca el algoritmo paralelo. Nota: la garantía de progreso débilmente paralelo asegura que uno de los hilos de ejecución que han dado un paso eventualmente dará otro paso, lo que no permite que los hilos entren en secciones críticas ni tomen bloqueos, porque el hilo que tiene el bloqueo puede no ser planificado nuevamente hasta que un hilo que intenta tomar el bloqueo haya salido.
4) El tipo de política de ejecución utilizado como tipo único para desambiguar la sobrecarga de algoritmos paralelos e indicar que la ejecución de un algoritmo paralelo puede ser vectorizada, p.ej., ejecutada en un solo hilo usando instrucciones que operan sobre múltiples elementos de datos.

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 termina mediante una excepción no capturada, se llama a std::terminate, pero las implementaciones pueden definir políticas de ejecución adicionales que manejen las excepciones de manera diferente.

Notas

Al usar una política de ejecución paralela, es responsabilidad del programador evitar condiciones de carrera y interbloqueos:

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
});

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 intercalarse. En todas las demás situaciones en C++, están secuenciadas de forma indeterminada (no se pueden intercalar). Debido a eso, los usuarios no pueden asignar ni desasignar memoria, adquirir mutex, usar especializaciones de std::atomic que no sean libres de bloqueos, o, en general, realizar cualquier operación no segura para vectorización al usar estas políticas (las funciones no seguras para vectorización son aquellas que se sincronizan-con otra función, p.ej. std::mutex::unlock se sincroniza-con el 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: lock_guard constructor calls m.lock()
    ++x;
});

Si la implementación no puede paralelizar o vectorizar (p.ej. debido a 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ítica de ejecución
(constante)