std::execution:: sequenced_policy, std::execution:: parallel_policy, std::execution:: parallel_unsequenced_policy, std::execution:: unsequenced_policy
|
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) |
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 });
` 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) |