std::execution::bulk, std::execution::bulk_chunked, std::execution::bulk_unchunked - cppreference.com (original) (raw)

Defined in header
std::execution::sender auto bulk( std::execution::sender auto input, std::integral auto size, auto&& policy, std::invocable<decltype(size), /*values-sent-by*/(input)...> function ); (1) (since 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), /*values-sent-by*/(input)...> function2 ); (2) (since C++26)
std::execution::sender auto bulk_unchunked( std::execution::sender auto input, std::integral auto size, std::invocable<decltype(size), decltype(size), /*values-sent-by*/(input)...> function ); (3) (since C++26)

[edit] Parameters

input - sender which once executed sends the values upon which the function executes
policy - the execution policy attached to function/function2
function - invocable to be called for every index in range [​0​, size), passing also the values produced by the input sender
function2 - same as function but called with a pair of indices (b, e), with b < e, so that, for each index i in range [[0, size) there is exactly one call to function2 so that b <= i < e.

[edit] Return value

Returns a sender describing the task graph described by the input sender, with an added node of invoking the provided function with indices in range [​0​, size), passing also the values sent by the input sender as arguments.

function/function2 is guaranteed to not begin executing until the returned sender is started.

[edit] Error completions

All errors passed in by input are forwarded.

In addition, the sender is allowed to complete with an std::exception_ptr error that contains:

[edit] Cancellation

The uncustomized std::execution::bulk, std::execution::bulk_chunk and std::execution::bulk_unchunked forward the stopped completion signal from input. They do not provide additional mechanism to produce stopped completion signal.

[edit] Notes

When calling std::execution::bulk and std::execution::bulk_chunked, different invocations of function/function2 may happen on the same execution agent.

When calling std::execution::bulk_unchunked, different invocations of function must happen on different execution agents.

The default implementation of std::execution::bulk is based on std::execution::bulk_chunked. While customizing std::execution::bulk is possible, it is expected that most of the time only std::execution::bulk_chunked is customized.

Without a customization of std::execution::bulk and std::execution::bulk_chunked, the behavior of std::execution::bulk and std::execution::bulk_chunk is to execute function serially, which is not particularly useful. Implementations are expected to have customizations that would make running std::execution::bulk and std::execution::bulk_chunked on different schedulers more useful.

std::execution::bulk_unchunked is meant to be used whenever function may have dependencies between different invocations, and it requires concurrent forward progress guarantees (parallel forward progress is not enough). Running std::execution::bulk_unchunked with a size of 1000 will require 1000 execution agents (e.g., threads) to run concurrently.

std::execution::bulk_unchunked does not require an execution policy, as is already expected for function to be able to run concurrently.

[edit] Examples

Possible usage of execution::bulk.

std::vector x; std::vector 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())

Possible usage of 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()