我正在尝试使用Intel TBB parallel_reduce获得由双精度数组成的数组元素的总和。但是,与OpenMP减少实施相比,结果有所不同。

这是OpenMP之一:

double dAverageTemp = 0.0;
#pragma omp parallel for reduction(+:dAverageTemp)
for (int i = 0; i < sCartesianSize; i++)
    dAverageTemp += pdTempCurr[i];


该代码返回正确的值“ 317.277493”;但是这个TBB代码:

double dAverageTemp = tbb::parallel_reduce(tbb::blocked_range<double*>(pdTempCurr, pdTempCurr + sCartesianSize - 1),
                                        0.0,
                                        [](const tbb::blocked_range<double*> &r, double value) -> double {
                                            return std::accumulate(r.begin(), r.end(), value);
                                        },
                                        std::plus<double>()
                                        );


坚持认为结果是“ 317.277193”。

我在这里想念什么?

最佳答案

尽管所有关于求和顺序的注释都完全正确,但是这里的简单事实是您的代码中有一个错误。所有std::thrust::tbb::算法或构造函数在定义范围时都遵循相同的原理,即表示从第一个元素采用到第一个元素不采用,例如在for ( auto it = v.begin(); it < v.end(); it++)

因此,在这里,您用于tbb::blocked_range的代码应升至pdTempCurr + sCartesianSize,而不是pdTempCurr + sCartesianSize - 1

它应该变成:

double dAverageTemp = tbb::parallel_reduce(tbb::blocked_range<double*>(pdTempCurr, pdTempCurr + sCartesianSize ),
                    0.0,
                    [](const tbb::blocked_range<double*> &r, double value) -> double {
                         return std::accumulate(r.begin(), r.end() value);
                    },
                    std::plus<double>()
              );


我的(疯狂的)猜测是pdTempCurr[sCartesianSize-1]0.0003附近,这将解释所经历的数值差异。

关于c++ - 双重返回不正确结果时的parallel_reduce,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33586737/

10-09 05:36
查看更多