std::execution::bulk, std::execution::bulk_chunked, std::execution::bulk_unchunked
| Definiert in Header <execution> |
||
| std::execution::sender auto bulk( std::execution::sender auto input, |
(1) | (seit C++26) |
| std::execution::sender auto bulk_chunked( std::execution::sender auto input, |
(2) | (seit C++26) |
| std::execution::sender auto bulk_unchunked( std::execution::sender auto input, |
(3) | (seit C++26) |
Inhalt |
[bearbeiten] Parameter
| input | - | Sender, der, sobald er ausgeführt wird, die Werte sendet, über die die Funktion ausgeführt wird |
| policy | - | die Ausführungsrichtlinie, die an function/function2 angehängt ist |
| Funktion | - | aufrufbar, die für jeden Index im Bereich aufgerufen werden soll [0, size), wobei auch die vom Eingabesender produzierten Werte übergeben werden |
| function2 | - | dasselbe wie function, aber aufgerufen mit einem Paar von Indizes (b, e), wobei b < e gilt, so dass für jeden Index i im Bereich [[0, size) genau ein Aufruf von function2 erfolgt, so dass b <= i < e gilt. |
[bearbeiten] Rückgabewert
Gibt einen Sender zurück, der den durch den Eingabesender beschriebenen Task-Graphen beschreibt, mit einem hinzugefügten Knoten, der die bereitgestellte Funktion mit Indizes im Bereich aufruft [0, size), wobei auch die vom Eingabesender gesendeten Werte als Argumente übergeben werden.
function/function2 wird garantiert erst dann ausgeführt, wenn der zurückgegebene Sender gestartet wird.
[bearbeiten] Fehlerabschlüsse
Alle Fehler, die von input übergeben werden, werden weitergeleitet.
Darüber hinaus darf der Sender mit einem Fehler vom Typ std::exception_ptr abgeschlossen werden, der Folgendes enthält:
- jede Ausnahme, die von function ausgelöst wird
- std::bad_alloc, wenn die Implementierung erforderliche Ressourcen nicht zuweisen kann
- eine Ausnahme, die von std::runtime_error abgeleitet ist, für andere interne Fehler (z. B. kann die Ausnahme nicht vom Ausführungskontext zum Aufrufer weitergeleitet werden).
[bearbeiten] Abbruch
Die unveränderten `std::execution::bulk`, `std::execution::bulk_chunk` und `std::execution::bulk_unchunked` leiten das gestoppte Abschluss-Signal von input weiter. Sie bieten keinen zusätzlichen Mechanismus zur Erzeugung eines gestoppten Abschluss-Signals.
[bearbeiten] Hinweise
Beim Aufruf von std::execution::bulk und std::execution::bulk_chunked können unterschiedliche Aufrufe von function/function2 auf demselben Ausführungsagenten erfolgen.
Beim Aufruf von std::execution::bulk_unchunked müssen unterschiedliche Aufrufe von function auf verschiedenen Ausführungsagenten erfolgen.
Die Standardimplementierung von std::execution::bulk basiert auf std::execution::bulk_chunked. Obwohl eine Anpassung von std::execution::bulk möglich ist, wird erwartet, dass meist nur std::execution::bulk_chunked angepasst wird.
Ohne eine Anpassung von std::execution::bulk und std::execution::bulk_chunked ist das Verhalten von std::execution::bulk und std::execution::bulk_chunk, dass function seriell ausgeführt wird, was nicht besonders nützlich ist. Es wird erwartet, dass Implementierungen Anpassungen vornehmen, die die Ausführung von std::execution::bulk und std::execution::bulk_chunked auf verschiedenen Schedulern nützlicher machen.
std::execution::bulk_unchunked ist für die Verwendung vorgesehen, wenn function Abhängigkeiten zwischen verschiedenen Aufrufen haben kann und Fortschrittsgarantien für gleichzeitigen Fortschritt erfordert (paralleler Fortschritt reicht nicht aus). Die Ausführung von std::execution::bulk_unchunked mit einer Größe von 1000 erfordert 1000 Ausführungsagenten (z. B. Threads), die gleichzeitig ausgeführt werden.
std::execution::bulk_unchunked erfordert keine Ausführungsrichtlinie, da bereits erwartet wird, dass function parallel ausgeführt werden kann.
[bearbeiten] Beispiele
Mögliche Verwendung von execution::bulk.
std::vector<double> x; std::vector<double> y; //... sender auto process_elements = just(get_coefficient()) | bulk(x.size(), [&](size_t i, double a) { y[i] = a * x[i] + y[i]; }); // process_elements describes the work described by calling a function to // get a coefficient `a`, and using it to execute // y[i] = a * x[i] + y[i] // for each `i` in range [0, x.size())
Mögliche Verwendung von execution::bulk_chunked.
std::vector<std::uint32_t> data = ...; std::atomic<std::uint32_t> sum{0}; sender auto s = bulk_chunked(just(), par, 100000, [&sum, &data](int begin, int end) { auto partial_sum = std::accumulate(data.begin() + begin, data.begin() + end, 0U); sum.fetch_add(partial_sum); }); // the atomic object will not be touched 100000 times; will execute faster than bulk()