Namespaces
Variants

std::experimental::parallel:: reduce

From cppreference.net
定义于头文件 <experimental/numeric>
template < class InputIt >

typename std:: iterator_traits < InputIt > :: value_type reduce (

InputIt first, InputIt last ) ;
(1) (并行性 TS)
template < class ExecutionPolicy, class InputIterator >

typename std:: iterator_traits < InputIt > :: value_type reduce (

ExecutionPolicy && policy, InputIt first, InputIt last ) ;
(2) (并行性 TS)
template < class InputIt, class T >
T reduce ( InputIt first, InputIt last, T init ) ;
(3) (并行性 TS)
template < class ExecutionPolicy, class InputIt, class T >
T reduce ( ExecutionPolicy && policy, InputIt first, InputIt last, T init ) ;
(4) (并行性 TS)
template < class InputIt, class T, class BinaryOp >
T reduce ( InputIt first, InputIt last, T init, BinaryOp binary_op ) ;
(5) (并行性 TS)
template < class ExecutionPolicy, class InputIt, class T, class BinaryOp >

T reduce ( ExecutionPolicy && policy,

InputIt first, InputIt last, T init, BinaryOp binary_op ) ;
(6) (并行性 TS)
1) 等同于 reduce ( first, last, typename std:: iterator_traits < InputIt > :: value_type { } )
3) 等同于 reduce ( first, last, init, std:: plus <> ( ) )
5) 将可能以未指定方式排列和聚合的范围 [ first , last ) 与初始值 init 通过 binary_op 进行归约。
2,4,6) (1,3,5) 相同,但根据 policy 执行。

如果 binary_op 不满足结合律或交换律,则行为是不确定的。

如果 binary_op 修改了 [ first , last ) 范围内的任何元素或使任何迭代器失效,则行为未定义。

目录

参数

first, last - 应用算法操作的元素范围
init - 广义求和的初始值
policy - 执行策略
binary_op - 二元 函数对象 ,将以未指定顺序应用于解引用输入迭代器的结果、其他 binary_op 的结果以及 init
类型要求
-
InputIt 必须满足 LegacyInputIterator 的要求。

返回值

init * first * ( first + 1 ) …… * ( 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

换句话说,范围中的元素可以按任意顺序进行分组和重新排列。

复杂度

O(last - first) binary_op 的应用。

异常

  • 如果作为算法一部分调用的函数执行抛出异常,
  • policy parallel_vector_execution_policy ,则调用 std::terminate
  • policy sequential_execution_policy parallel_execution_policy ,算法将以包含所有未捕获异常的 exception_list 退出。若仅存在一个未捕获异常,算法可能直接重新抛出该异常而不将其包装在 exception_list 中。遇到第一个异常后,算法在返回前将执行多少工作未作明确规定。
  • policy 为其他类型,其行为由实现定义。
  • 如果算法无法分配内存(无论是为自身分配还是在处理用户异常时构造 exception_list ),将抛出 std::bad_alloc

注释

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

  • 如果 policy sequential_execution_policy 的实例,所有操作将在调用线程中执行。
  • 如果 policy parallel_execution_policy 的实例,操作可能在未指定数量的线程中执行,彼此之间以不确定的顺序进行。
  • 如果 policy parallel_vector_execution_policy 的实例,执行可能同时并行化和向量化:函数体边界不被遵守,用户代码可能以任意方式重叠和组合(特别地,这意味着用户提供的可调用对象不得通过获取互斥锁来访问共享资源)。

示例

reduce 是 std::accumulate 的无序版本:

#include <chrono>
#include <experimental/execution_policy>
#include <experimental/numeric>
#include <iostream>
#include <numeric>
#include <vector>
int main()
{
    std::vector<double> v(10'000'007, 0.5);
    {
        auto t1 = std::chrono::high_resolution_clock::now();
        double result = std::accumulate(v.begin(), v.end(), 0.0);
        auto t2 = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> ms = t2 - t1;
        std::cout << std::fixed << "std::accumulate result " << result
                  << " took " << ms.count() << " ms\n";
    }
    {
        auto t1 = std::chrono::high_resolution_clock::now();
        double result = std::experimental::parallel::reduce(
                            std::experimental::parallel::par,
                            v.begin(), v.end());
        auto t2 = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> ms = t2 - t1;
        std::cout << "parallel::reduce result "
                  << result << " took " << ms.count() << " ms\n";
    }
}

可能的输出:

std::accumulate result 5000003.50000 took 12.7365 ms
parallel::reduce result 5000003.50000 took 5.06423 ms

参见

对范围内的元素进行求和或折叠操作
(函数模板)
对范围内的元素应用函数,并将结果存储到目标范围
(函数模板)
(parallelism TS)
应用函数对象后以无序方式规约
(函数模板)