Namensräume
Varianten
Aktionen

std::execution::bulk, std::execution::bulk_chunked, std::execution::bulk_unchunked

Von cppreference.com
< cpp‎ | execution
 
 
 
Definiert in Header <execution>
std::execution::sender

auto bulk( std::execution::sender auto input,
           std::integral auto size,
           auto&& policy,
           std::invocable<decltype(size),

                          /*werte-von-input-gesendet*/(input)...> function );
(1) (seit C++26)
std::execution::sender

auto bulk_chunked( std::execution::sender auto input,
                   std::integral auto size,
                   auto&& policy,
                   std::invocable<decltype(size), decltype(size),

                                  /*werte-von-input-gesendet*/(input)...> function2 );
(2) (seit C++26)
std::execution::sender

auto bulk_unchunked( std::execution::sender auto input,
                     std::integral auto size,
                     std::invocable<decltype(size), decltype(size),

                                    /*werte-von-input-gesendet*/(input)...> function );
(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 [0size), wobei auch die vom Eingabesender produzierten Werte übergeben werden
function2 - dasselbe wie function, aber aufgerufen mit einem Paar von Indizes (be), wobei b < e gilt, so dass für jeden Index i im Bereich [[0size) 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 [0size), 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()