std::execution:: sequenced_policy, std::execution:: parallel_policy, std::execution:: parallel_unsequenced_policy, std::execution:: unsequenced_policy
|
Definiert im Header
<execution>
|
||
|
class
sequenced_policy
{
/* unspecified */
}
;
|
(1) | (seit C++17) |
|
class
parallel_policy
{
/* unspecified */
}
;
|
(2) | (seit C++17) |
|
class
parallel_unsequenced_policy
{
/* unspecified */
}
;
|
(3) | (seit C++17) |
|
class
unsequenced_policy
{
/* unspecified */
}
;
|
(4) | (seit C++20) |
Während der Ausführung eines parallelen Algorithmus mit einer dieser Ausführungsrichtlinien, wenn der Aufruf einer Elementzugriffsfunktion über eine nicht abgefangene Ausnahme beendet wird, std::terminate aufgerufen, aber die Implementierungen können zusätzliche Ausführungsrichtlinien definieren, die Ausnahmen anders behandeln.
Hinweise
Bei Verwendung der parallelen Ausführungsrichtlinie liegt es in der Verantwortung des Programmierers, Datenrennen und Deadlocks zu vermeiden:
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); // Fehler: Datenwettlauf });
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) { } // Fehler: setzt Ausführungsreihenfolge voraus });
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; // korrekt });
Unsequenced-Ausführungsrichtlinien sind der einzige Fall, in dem Funktionsaufrufe unsequenced zueinander sind, was bedeutet, dass sie verschachtelt werden können. In allen anderen Situationen in C++ sind sie indeterminately-sequenced (können nicht verschachtelt werden). Aus diesem Grund ist es Benutzern nicht erlaubt, Speicher zu allokieren oder freizugeben, Mutexe zu erwerben, nicht lockfreie std::atomic Spezialisierungen zu verwenden oder allgemein vektorisierungs-unsichere Operationen durchzuführen, wenn diese Richtlinien verwendet werden (vektorisierungs-unsichere Funktionen sind solche, die mit einer anderen Funktion synchronisieren, z.B. std::mutex::unlock synchronisiert mit dem nächsten 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); // Fehler: lock_guard-Konstruktor ruft m.lock() auf ++x; });
Wenn die Implementierung keine Parallelisierung oder Vektorisierung durchführen kann (z.B. aufgrund von Ressourcenmangel), können alle Standard-Ausführungsrichtlinien auf sequentielle Ausführung zurückgreifen.
Siehe auch
|
(C++17)
(C++17)
(C++17)
(C++20)
|
Globale Ausführungsrichtlinien-Objekte
(Konstante) |