并行减少(例如求和)hpx::futures<double> 的向量

Posted

技术标签:

【中文标题】并行减少(例如求和)hpx::futures<double> 的向量【英文标题】:Parallel reduce (e.g. sum) a vector of hpx::futures<double> 【发布时间】:2019-01-31 21:18:50 【问题描述】:

我们目前正在尝试为数值模拟实施红黑高斯-赛德尔求解器。

为此,我们将模拟区域划分为大小相等的子网格。我们能够在具有正确依赖关系和hpx::dataflow 对象的每个子网格上异步执行压力方程的红黑循环。

但现在我们有以下问题:在每第 n 个循环之后,我们必须执行一次残差计算以确定我们是否已经收敛。

因此,最佳解决方案是,我们分别/异步地开始每个局部残差计算,然后对 hpx::future&lt;double&gt; 的向量求和。借助 HPX 期货的想法,可以得出最佳解决方案,即我们尽快总结所有要素。

但到目前为止,我们只能想出以下代码:

#include <hpx/hpx_main.hpp>
#include <hpx/hpx.hpp>
#include <memory>
#include <iostream>

class A 
public:
  double residual() 
    // Calculate actual local residual
    return 1.0;
  
;

int main() 
  // Create instances
  std::vector<A> vec(3);
  std::vector<hpx::shared_future<double>> res(vec.size());

  // asynchronous launch resdiual calculation
  for (size_t i = 0; i < res.size(); ++i) 
    res[i] = hpx::async( &A::residual, &vec[i] );
  

  double residual = 0.0;
  for (size_t i = 0; i < res.size(); ++i) 
    residual += res[i].get();
  

  std::cout << "residual: " << residual << std::endl;

  return 0;

这远非最佳。在最坏的情况下,它的性能就像一个全局屏障,然后是所有元素的纯顺序总和。

所以我们的问题是我们如何才能并行实现这个“HPX”?

2019 年 2 月 2 日更新:

我们已经重写了我们的代码,因此我们不能完全异步地开始我们的残差计算,而是基于通过hpx::dataflow 对象的数据依赖关系。

  // asynchronous launch resdiual calculation
  for (size_t i = 0; i < res.size(); ++i) 
    res[i] = hpx::dataflow( hpx::util::unwrapping(&A::residual), &vec[i], *DEPENDENCIES* );
  

是否也可以使用数据流对象调用@Mike van Dyke 代码,或者是否有其他解决方案?

(提示:由于template argument deduction/substitution failed 错误,我没有让您的代码工作)

【问题讨论】:

你需要中间结果res[i] = hpx::async( &amp;A::residual, &amp;vec[i] );吗? std::vector&lt;A&gt; vec(3) 真的只有 3 号吗? 我们不需要中间结果,只需要最后的残差来检查收敛性。此代码只是演示问题的最小工作示例。实际大小基于给定模拟的粒度。 【参考方案1】:

您可以使用transform_reduce 模式来实现您想要实现的目标:

std::vector<A> vec(300);
double res = hpx::parallel::transform_reduce(hpx::parallel::execution::par,        
                     vec.begin(), vec.end(),                      \\ (1)                         
                     0, [](double a, double b) return a + b; ,  \\ (2)
                     [](const A& a_ref) return a_ref.residual(); );   \\ (3)

这段代码会计算Avec中的残差(3)(1),然后将所有结果相加(2)。

【讨论】:

这将无法编译,因为参数序列不正确(请参阅:en.cppreference.com/w/cpp/algorithm/transform_reduce)。正确的参数序列如下所示:***.com/a/54508775/269943. @hkaiser 即使使用此参数序列,代码也不会出现。见https://***.com/questions/54504021/hpx-transform-reduce?noredirect=1&lq=1 是的,我后来自己也注意到了。为我辩护:MSVC 接受了我发布的代码(它倾向于允许将 const 引用绑定到非 const 引用 - 这是一个众所周知的错误)。

以上是关于并行减少(例如求和)hpx::futures<double> 的向量的主要内容,如果未能解决你的问题,请参考以下文章

对数时间并行减少

并行求和一个数组

C++ Armadillo 和 OpenMp:外积求和的并行化 - 定义 Armadillo 矩阵的约简

将数组的并行流减少为单个数组

对浮点数求和的最佳 OpenCL 2 内核是啥?

不了解使用最大运算 OpenMP 程序并行减少的输出?