Namespaces
Variants

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

From cppreference.net
Определено в заголовочном файле <execution>
std :: execution :: sender

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

/*значения-отправленные-через*/ ( input ) ... > function ) ;
(1) (начиная с 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 ) ,

/*значения-отправленные-через*/ ( input ) ... > function2 ) ;
(2) (начиная с C++26)
std :: execution :: sender

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

/*значения-отправленные-через*/ ( input ) ... > function ) ;
(3) (начиная с C++26)

Содержание

Параметры

input - отправитель, который после выполнения передает значения, на которых выполняется функция
policy - политика выполнения, присоединенная к execution policy attached to function / function2
function - вызываемый объект, который будет вызываться для каждого индекса в диапазоне [ 0 , size ) , передавая также значения, произведенные отправителем input
function2 - аналогично function , но вызывается с парой индексов ( b , e ) , где b < e , так что для каждого индекса i в диапазоне [ [ 0 , size ) существует ровно один вызов function2 , для которого b <= i < e .

Возвращаемое значение

Возвращает отправитель, описывающий граф задач, представленный входным отправителем, с добавленным узлом вызова предоставленной функции с индексами в диапазоне [ 0 , size ) , передавая также значения, отправленные входным отправителем, в качестве аргументов.

function / function2 гарантированно не начнет выполнение до тех пор, пока возвращаемый отправитель не будет запущен.

Завершения ошибок

Все ошибки, переданные через input , перенаправляются.

Кроме того, отправителю разрешается завершить с ошибкой std::exception_ptr , которая содержит:

  • любое исключение, выброшенное function
  • std::bad_alloc если реализация не может выделить необходимые ресурсы
  • исключение, производное от std::runtime_error для других внутренних ошибок (например, невозможно передать исключение из контекста выполнения вызывающей стороне).

Отмена

Ненастроенные std::execution::bulk , std::execution::bulk_chunk и std::execution::bulk_unchunked передают сигнал остановки завершения от input . Они не предоставляют дополнительных механизмов для генерации сигнала остановки завершения.

Примечания

При вызове std::execution::bulk и std::execution::bulk_chunked различные вызовы function / function2 могут выполняться на одном и том же агенте выполнения.

При вызове std::execution::bulk_unchunked различные вызовы function должны выполняться на разных агентах выполнения.

Реализация по умолчанию std::execution::bulk основана на std::execution::bulk_chunked . Хотя настройка std::execution::bulk возможна, предполагается, что в большинстве случаев настраивается только std::execution::bulk_chunked .

Без специализации std::execution::bulk и std::execution::bulk_chunked поведение std::execution::bulk и std::execution::bulk_chunk заключается в последовательном выполнении function , что не особенно полезно. Ожидается, что реализации будут иметь специализации, которые сделают выполнение std::execution::bulk и std::execution::bulk_chunked на различных планировщиках более полезным.

std::execution::bulk_unchunked предназначен для использования в случаях, когда function может иметь зависимости между различными вызовами, и требует гарантий конкурентного прогресса (параллельного прогресса недостаточно). Запуск std::execution::bulk_unchunked с размером 1000 потребует 1000 агентов выполнения (например, потоков) для конкурентного выполнения.

std::execution::bulk_unchunked не требует политики выполнения, так как уже предполагается, что function может выполняться параллельно.

Примеры

Возможное использование 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 описывает работу, заключающуюся в вызове функции для
// получения коэффициента `a` и его использовании для выполнения
//   y[i] = a * x[i] + y[i]
// для каждого `i` в диапазоне [0, x.size())

Возможное использование 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);
    });
// атомный объект не будет обрабатываться 100000 раз; выполнится быстрее чем bulk()