我们目前正在尝试为数字模拟实现红黑色高斯-赛德尔(Gauss-Seidel)求解器。

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

但是现在我们遇到了以下问题:在每个第n个周期之后,我们必须执行残差计算来确定是否已经收敛。

因此,最佳解决方案是,我们分别/异步地开始每个局部残差计算,然后对hpx::future<double>的 vector 求和。 HPX future 的想法可能会导致最佳解决方案,即我们会尽快汇总所有要素。

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

#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”?

更新02.02.2019:

我们已经重写了代码,以使我们无法完全异步地进行残差计算,而是基于基于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错误,我的代码无法正常工作)

最佳答案

您可以使用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)

此代码将计算A(1)中每个vec的残差(3),然后将所有结果求和(2)。

关于c++ - 并行化简(例如求和)hpx::futures <double>的 vector ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54469381/

10-11 16:31