【问题标题】:Parallel reduction of an array on CPU在 CPU 上并行减少数组
【发布时间】:2012-02-22 17:31:09
【问题描述】:

有没有办法在 C/C++ 中并行减少 CPU 上的数组?我最近了解到使用openmp 是不可能的。还有其他选择吗?

【问题讨论】:

  • 您的意思是“除非您使用最新的、符合标准的 Fortran 编译器,否则无法使用 OpenMP”,不是吗?
  • @talonmies 使用 C 或 C++。我刚刚编辑过!
  • 您可以使用前缀和来编写并行归约算法。 en.wikipedia.org/wiki/Prefix_sum
  • @perreal 我在考虑更多的 API/内置算法来做到这一点。

标签: c++ c openmp parallel-processing tbb


【解决方案1】:

已添加:请注意,您可以按照here 所述的方式使用 OpenMP 实现“自定义”缩减。


对于 C++:使用 Intel's TBB 中的 parallel_reduce(SO 标记:),您可以减少复杂类型,例如数组和结构。尽管与 OpenMP 的缩减子句相比,所需的代码量可能要大得多。

例如,让我们并行化矩阵到向量乘法的简单实现:y=Cx。串行代码由两个循环组成:

double x[N], y[M], C[N][M];
// assume x and C are initialized, and y consists of zeros
for(int i=0; i<N; ++i)
  for(int j=0; j<M; ++j) 
    y[j] += C[i][j]*x[i];

通常,为了使其并行化,交换循环以使外部循环迭代独立并并行处理它们:

#pragma omp parallel for
for(int j=0; j<M; ++j) 
  for(int i=0; i<N; ++i)
    y[j] += C[i][j]*x[i];

但这并不总是好主意。如果 M 小而 N 大,则交换循环不会提供足够的并行度(例如,考虑计算 M 维空间中 N 个点的加权 centroidC 是点数组,@ 987654330@ 是权重数组)。所以减少一个数组(即一个点)会很有帮助。以下是使用 TBB 的方法(抱歉,代码未经测试,可能出现错误):

struct reduce_body {
  double y_[M]; // accumulating vector
  double (& C_)[N][M]; // reference to a matrix
  double (& x_)[N];    // reference to a vector

  reduce_body( double (&C)[N][M], double (&x)[N] )  : C_(C), x_(x) {
    for (int j=0; j<M; ++j) y_[j] = 0.0; // prepare for accumulation
  }
  // splitting constructor required by TBB
  reduce_body( reduce_body& rb, tbb::split ) : C_(rb.C_), x_(rb.x_) { 
    for (int j=0; j<M; ++j) y_[j] = 0.0;
  }
  // the main computation method
  void operator()(const tbb::blocked_range<int>& r) {
    // closely resembles the original serial loop
    for (int i=r.begin(); i<r.end(); ++i) // iterates over a subrange in [0,N)
      for (int j=0; j<M; ++j)
        y_[j] += C_[i][j]*x_[i];
  }
  // the method to reduce computations accumulated in two bodies
  void join( reduce_body& rb ) {
    for (int j=0; j<M; ++j) y_[j] += rb.y_[j];
  }
};
double x[N], y[M], C[N][M];
...
reduce_body body(C, x);
tbb::parallel_reduce(tbb::blocked_range<int>(0,N), body);
for (int j=0; j<M; ++j)
  y[j] = body.y_[j]; // copy to the destination array

免责声明:我隶属于 TBB。

【讨论】:

  • 你好@Alexey,没有足够的关于数组parallel_reduce 的文档,大部分是为了简单的减少。你能链接到一个来源吗?。
  • 非常感谢@Alexey 提供的代码。但是,我不明白为什么要使用 a[j]?
  • 对不起,我的错误,现在修正了。
猜你喜欢
  • 1970-01-01
  • 2019-10-01
  • 2021-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 2018-10-09
  • 1970-01-01
相关资源
最近更新 更多