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 ) ,

/*values-sent-by*/ ( 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 ) ,

/*values-sent-by*/ ( 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 ) ,

/*values-sent-by*/ ( input ) ... > function ) ;
(3) (C++26 起)

目录

参数

input - 输入发送器,执行后会传递函数执行所需的值
policy - 附加到 function / function2 执行策略
function - 可调用对象,将对范围 [ 0 , size ) 内的每个索引进行调用,同时传入输入发送器产生的值
function2 - function 类似,但通过索引对 ( b , e ) 调用(需满足 b < e ),确保对于范围 [ [ 0 , size ) 内的每个索引 i ,都存在唯一一次 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 在不同调用间可能存在依赖关系,且需要并发向前推进保证时(仅并行向前推进不足够)。使用大小为1000的 std::execution::bulk_unchunked 将需要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]
// 对于每个在范围 [0, x.size()) 内的 `i` 所定义的工作

可能的用法 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);
    });
// 原子对象不会被访问10万次;执行速度将比 bulk() 更快