std::experimental::parallel::transform_reduce

来自cppreference.com
在标头 <experimental/numeric> 定义
template< class InputIt, class UnaryOp, class T, class BinaryOp >

T transform_reduce( InputIt first, InputIt last,

                    UnaryOp unary_op, T init, BinaryOp binary_op );
(1) (并行 TS)
template< class ExecutionPolicy,

          class InputIt, class UnaryOp, class T, class BinaryOp >
T transform_reduce( ExecutionPolicy&& policy,
                    InputIt first, InputIt last,

                    UnaryOp unary_op, T init, BinaryOp binary_op );
(2) (并行 TS)

对范围 [firstlast) 中的每个元素应用 unary_op,并将其结果(可能以未指明的方式排列和聚合)和初值 init 一起在 binary_op 上归约。

如果 binary_op 不可结合或不可交换,则其行为不确定。

如果 unary_opbinary_op 修改了任何元素或使 [firstlast) 中的任何迭代器失效,则其行为未定义。

参数

first, last - 要向其运用算法的元素范围
init - 广义和的初值
policy - 执行策略
unary_op - 将应用于输入元素范围的每个元素的一元函数对象 (FunctionObject) 。其返回类型必须课接受为 binary_op 的输入
binary_op - 将以未指明顺序应用于 unary_op 的结果,其他 binary_op 的结果和 init 上的二元函数对象 (FunctionObject)
类型要求
-
InputIt 必须满足老式输入迭代器 (LegacyInputIterator)

返回值

initunary_op(*first), unary_op(*(first + 1)), ... unary_op(*(last - 1))binary_op 上的广义和, 其中广义和 GSUM(op, a
1
, ..., a
N
)
定义如下:

  • 如果 N = 1,则为 a
    1
  • 如果 N > 1,则为 op(GSUM(op, b
    1
    , ..., b
    K
    ), GSUM(op, b
    M
    , ..., b
    N
    ))
    其中
  • b
    1
    , ..., b
    N
    可以为 a1, ..., aN 的任意排列,且
  • 1 < K + 1 = M ≤ N

换言之,unary_op 的结果可能以任意顺序分钟和排布。

复杂度

O(last - first) 次运用 unary_opbinary_op

异常

  • 如果作为算法一部分而调用的函数执行抛出了异常,
  • 如果 policyparallel_vector_execution_policy,则调用 std::terminate
  • 如果 policysequential_execution_policyparallel_execution_policy,则算法以抛出包含所有未捕获异常的 exception_list 而退出。如果只有一个未捕获异常,则算法可能重新抛出它而不将之包装到 exception_list 中。未指明算法在发生第一个异常后和返回前会做多少工作。
  • 如果 policy 是某个其他类型,则其行为由实现定义。
  • 如果算法分配内存失败(为其自身,或在处理用户异常时用于构造 exception_list),则抛出 std::bad_alloc

注解

unary_op 不对 init 运用。

如果范围为空,则返回未修改的 init

  • 如果 policysequential_execution_policy 的实例,则所有操作在调用方线程中实施。
  • 如果 policyparallel_execution_policy 的实例,则可以在未指明数量的线程中实施操作,互相之间顺序不确定。
  • 如果 policyparallel_vector_execution_policy 的实例,则其执行可以同时并行化和向量化:不遵循函数体边界,且用户代码可能发生重叠并以任意方式合并(尤其是,这蕴含了用户提供的 Callable 不能为访问共享资源获取互斥体)。

示例

transform_reduce 可以用于并行化 std::inner_product

#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple.hpp>
#include <experimental/execution_policy>
#include <experimental/numeric>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
 
int main()
{
    std::vector<double> xvalues(10007, 1.0), yvalues(10007, 1.0);
 
    double result = std::experimental::parallel::transform_reduce(
        std::experimental::parallel::par,
        boost::iterators::make_zip_iterator(
            boost::make_tuple(std::begin(xvalues), std::begin(yvalues))),
        boost::iterators::make_zip_iterator(
            boost::make_tuple(std::end(xvalues), std::end(yvalues))),
        [](auto r) { return boost::get<0>(r) * boost::get<1>(r); }
        0.0,
        std::plus<>()
    );
    std::cout << result << '\n';
}

输出:

10007

参阅

对一个范围内的元素求和或折叠
(函数模板)
将一个函数应用于某一范围的各个元素,并在目标范围存储结果
(函数模板)
(并行 TS)
类似 std::accumulate,但不按顺序进行
(函数模板)