Namespaces
Variants

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

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
execution::sequenced_policy execution::parallel_policy execution::parallel_unsequenced_policy execution::parallel_unsequenced
(C++17) (C++17) (C++17) (C++20)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Défini dans l'en-tête <execution>
class sequenced_policy { /* unspecified */ } ;
(1) (depuis C++17)
class parallel_policy { /* unspecified */ } ;
(2) (depuis C++17)
class parallel_unsequenced_policy { /* unspecified */ } ;
(3) (depuis C++17)
class unsequenced_policy { /* unspecified */ } ;
(4) (depuis C++20)
1) Le type de politique d'exécution utilisé comme type unique pour lever l'ambiguïté de la surcharge des algorithmes parallèles et exiger que l'exécution d'un algorithme parallèle ne puisse pas être parallélisée. Les invocations des fonctions d'accès aux éléments dans les algorithmes parallèles invoqués avec cette politique (généralement spécifiée comme std::execution::seq ) sont séquencées de manière indéterminée dans le thread appelant.
2) Le type de politique d'exécution utilisé comme type unique pour lever l'ambiguïté de la surcharge des algorithmes parallèles et indiquer que l'exécution d'un algorithme parallèle peut être parallélisée. Les invocations des fonctions d'accès aux éléments dans les algorithmes parallèles invoqués avec cette politique (généralement spécifiée comme std::execution::par ) sont autorisées à s'exécuter soit dans le thread d'appel, soit dans un thread créé implicitement par la bibliothèque pour supporter l'exécution des algorithmes parallèles. Toutes ces invocations s'exécutant dans le même thread sont séquencées de manière indéterminée les unes par rapport aux autres. Si les threads d'exécution créés par std::thread ou std::jthread fournissent des garanties de progression concurrente vers l'avant, alors les threads d'exécution créés par la bibliothèque fournissent des garanties de progression parallèle vers l'avant. Sinon, la garantie de progression fournie est définie par l'implémentation. Note : la progression parallèle vers l'avant garantit que si un thread d'exécution effectue une étape, il en effectuera éventuellement une autre, permettant aux threads d'entrer dans les sections critiques et de prendre des verrous, car le thread qui possède le verrou sera éventuellement replanifié et pourra le libérer.
3) Le type de politique d'exécution utilisé comme type unique pour lever l'ambiguïté de la surcharge des algorithmes parallèles et indiquer que l'exécution d'un algorithme parallèle peut être parallélisée, vectorisée ou migrée entre les threads (par exemple par un ordonnanceur à vol de tâches parentes). Les invocations des fonctions d'accès aux éléments dans les algorithmes parallèles invoqués avec cette politique sont autorisées à s'exécuter de manière non ordonnée dans des threads non spécifiés, et non séquencées les unes par rapport aux autres au sein de chaque thread. Les invocations des fonctions d'accès aux éléments dans les algorithmes parallèles invoqués avec cette politique ne sont pas autorisées à invoquer des opérations non sûres pour la vectorisation, comme celles spécifiées par la bibliothèque standard pour synchroniser, y compris celles de std::atomic et d'autres primitives de concurrence. Si les threads d'exécution créés par std::thread ou std::jthread fournissent des garanties de progression concurrente vers l'avant, alors les threads d'exécution créés par la bibliothèque fournissent des garanties de progression faiblement parallèle vers l'avant. Sinon, la garantie de progression fournie est celle du thread invoquant l'algorithme parallèle. Remarque : les garanties de progression faiblement parallèle assurent que l'un des threads d'exécution ayant effectué une étape finira par en effectuer une autre, ce qui n'autorise pas les threads à entrer dans des sections critiques ou à prendre des verrous, car le thread qui détient le verrou risque de ne pas être replanifié tant qu'un thread tentant de prendre le verrou n'est pas sorti.
4) Le type de politique d'exécution utilisé comme type unique pour lever l'ambiguïté du surchargement des algorithmes parallèles et indiquer que l'exécution d'un algorithme parallèle peut être vectorisée, par exemple, exécutée sur un seul thread en utilisant des instructions qui opèrent sur plusieurs éléments de données.

Lors de l'exécution d'un algorithme parallèle avec l'une de ces politiques d'exécution, si l'invocation d'une fonction d'accès aux éléments se termine via une exception non capturée, std::terminate est appelée, mais les implémentations peuvent définir des politiques d'exécution supplémentaires qui gèrent les exceptions différemment.

Notes

Lors de l'utilisation de la politique d'exécution parallèle, il est de la responsabilité du programmeur d'éviter les conditions de course et les interblocages :

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); // Erreur : course aux données
});
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) { } // Erreur : suppose un ordre d'exécution
});
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
});
**Note:** Le code C++ n'a pas été traduit car il se trouve dans des balises `
` et contient des termes spécifiques au C++ qui doivent être préservés. Seul le commentaire "correct" a été traduit en "correct" en français.

Les politiques d'exécution non séquencées sont le seul cas où les appels de fonction sont non séquencés les uns par rapport aux autres, ce qui signifie qu'ils peuvent être entrelacés. Dans toutes les autres situations en C++, ils sont séquencés de manière indéterminée (ne peuvent pas être entrelacés). Pour cette raison, les utilisateurs ne sont pas autorisés à allouer ou désallouer de la mémoire, acquérir des mutex, utiliser des spécialisations std::atomic non lock-free, ou, en général, effectuer toute opération non sûre pour la vectorisation lors de l'utilisation de ces politiques (les fonctions non sûres pour la vectorisation sont celles qui se synchronisent avec une autre fonction, par exemple std::mutex::unlock se synchronise avec le prochain 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); // Erreur : le constructeur de lock_guard appelle m.lock()
    ++x;
});

Si l'implémentation ne peut pas paralléliser ou vectoriser (par exemple en raison d'un manque de ressources), toutes les politiques d'exécution standard peuvent revenir à une exécution séquentielle.

Voir aussi

(C++17) (C++17) (C++17) (C++20)
objets globaux de politique d'exécution
(constante)