Namespaces
Variants

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

Von de.cppreference.net
 
 
Algorithmen-Bibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum-/Maximumoperationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
Definiert in 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)
1) Der Ausführungsrichtlinientyp, der als eindeutiger Typ verwendet wird, um die Überladung paralleler Algorithmen zu disambiguieren und zu verlangen, dass die Ausführung eines parallelen Algorithmus nicht parallelisiert werden darf. Die Aufrufe von Elementzugriffsfunktionen in parallelen Algorithmen, die mit dieser Richtlinie aufgerufen werden (normalerweise angegeben als std::execution::seq), sind im aufrufenden Thread unbestimmt sequenziert.
2) Der Ausführungsrichtlinientyp, der als eindeutiger Typ verwendet wird, um die Überladung paralleler Algorithmen zu disambiguieren und anzuzeigen, dass die Ausführung eines parallelen Algorithmus parallelisiert werden kann. Die Aufrufe von Elementzugriffsfunktionen in parallelen Algorithmen, die mit dieser Richtlinie aufgerufen werden (normalerweise angegeben als std::execution::par), dürfen entweder im aufrufenden Thread oder in einem Thread ausgeführt werden, der implizit von der Bibliothek zur Unterstützung der parallelen Algorithmusausführung erstellt wurde. Solche Aufrufe, die im selben Thread ausgeführt werden, sind gegeneinander unbestimmt sequenziert. Wenn die von std::thread oder std::jthread erstellten Ausführungsthreads nebenläufige Fortschrittsgarantien bieten, dann bieten die von der Bibliothek erstellten Ausführungsthreads parallele Fortschrittsgarantien. Andernfalls ist die bereitgestellte Fortschrittsgarantie implementierungsdefiniert. Hinweis: Parallele Fortschrittsgarantien bedeuten, dass ein Ausführungsthread, der einen Schritt macht, irgendwann einen weiteren Schritt machen wird, sodass Threads in kritische Abschnitte eintreten und Sperren übernehmen können, da der Thread, der die Sperre hat, irgendwann wieder eingeplant wird und sie freigeben kann.
3) Der Ausführungsrichtlinientyp, der als eindeutiger Typ verwendet wird, um die Überladung paralleler Algorithmen zu disambiguieren und anzuzeigen, dass die Ausführung eines parallelen Algorithmus parallelisiert, vektorisiert oder zwischen Threads migriert werden kann (z.B. durch einen Parent-Stealing-Scheduler). Die Aufrufe von Elementzugriffsfunktionen in parallelen Algorithmen, die mit dieser Richtlinie aufgerufen werden, dürfen in ungeordneter Weise in unspezifizierten Threads ausgeführt werden und sind innerhalb jedes Threads unsequenziert zueinander. Die Aufrufe von Elementzugriffsfunktionen in parallelen Algorithmen, die mit dieser Richtlinie aufgerufen werden, dürfen keine vektorisierungsunsicheren Operationen aufrufen, wie sie von der Standardbibliothek zur Synchronisation spezifiziert werden, einschließlich derer von std::atomic und anderen Nebenläufigkeitsprimitiven. Wenn die von std::thread oder std::jthread erstellten Ausführungsthreads nebenläufige Fortschrittsgarantien bieten, dann bieten die von der Bibliothek erstellten Ausführungsthreads schwach parallele Fortschrittsgarantien. Andernfalls ist die bereitgestellte Fortschrittsgarantie die des Threads, der den parallelen Algorithmus aufruft. Hinweis: Schwach parallele Fortschrittsgarantien bedeuten, dass einer der Ausführungsthreads, die einen Schritt gemacht haben, irgendwann einen weiteren Schritt machen wird, was es Threads nicht erlaubt, in kritische Abschnitte einzutreten oder Sperren zu übernehmen, da der Thread, der die Sperre hat, möglicherweise erst dann wieder eingeplant wird, wenn ein Thread, der versucht, die Sperre zu erlangen, beendet ist.
4) Der Ausführungsrichtlinientyp, der als eindeutiger Typ verwendet wird, um die Überladung paralleler Algorithmen zu disambiguieren und anzuzeigen, dass die Ausführung eines parallelen Algorithmus vektorisiert werden kann, z.B. auf einem einzelnen Thread unter Verwendung von Anweisungen, die auf mehreren Datenelementen operieren.

Während der Ausführung eines parallelen Algorithmus mit einer dieser Ausführungsrichtlinien wird std::terminate aufgerufen, wenn ein Aufruf einer Elementzugriffsfunktion durch eine nicht gefangene Ausnahme beendet wird, aber die Implementierungen können zusätzliche Ausführungsrichtlinien definieren, die anders mit Ausnahmen umgehen.

Anmerkungen

Bei Verwendung einer parallelen Ausführungsrichtlinie liegt es in der Verantwortung des Programmierers, Datenwettläufe 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); // 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
});

Unsequenzierte Ausführungsrichtlinien sind der einzige Fall, in dem Funktionsaufrufe unsequenziert zueinander sind, was bedeutet, dass sie verschachtelt werden können. In allen anderen Situationen in C++ sind sie unbestimmt sequenziert (können nicht verschachtelt werden). Aus diesem Grund ist es Benutzern nicht erlaubt, Speicher zu allozieren oder freizugeben, Mutexe zu erwerben, nicht-sperrfreie std::atomic-Spezialisierungen zu verwenden oder allgemein vektorisierungsunsichere Operationen durchzuführen, wenn diese Richtlinien verwendet werden (vektorisierungsunsichere Funktionen sind solche, die mit einer anderen Funktion synchronisieren, z.B. synchronisiert std::mutex::unlock 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); // Error: lock_guard constructor calls m.lock()
    ++x;
});

Wenn die Implementierung nicht parallelisieren oder vektorisieren kann (z.B. aufgrund fehlender Ressourcen), können alle Standard-Ausführungsrichtlinien auf sequenzielle Ausführung zurückfallen.

Siehe auch

(C++17)(C++17)(C++17)(C++20)
Globale Ausführungsrichtlinienobjekte
(Konstante)