C++ Armadillo和OpenMP: 并行化外积求和 - 为Armadillo矩阵定义归约

3

我正在尝试使用OpenMP并行化一个for循环,该循环对Armadillo矩阵进行求和。我有以下代码:

#include <armadillo>
#include <omp.h>

int main()
{

        arma::mat A = arma::randu<arma::mat>(1000,700);
        arma::mat X = arma::zeros(700,700);
        arma::rowvec point = A.row(0);

        # pragma omp parallel for shared(A) reduction(+:X)
        for(unsigned int i = 0; i < A.n_rows; i++){
                arma::rowvec diff = point - A.row(i);
                X += diff.t() * diff; // Adding the matrices to X here
        }

}

我遇到了这个错误:

[Legendre@localhost ~]$ g++ test2.cpp -o test2 -O2 -larmadillo -fopenmp
test2.cpp: In function ‘int main()’:
test2.cpp:11:52: error: user defined reduction not found for ‘X’

我研究了有关定义约简的内容,但是没有找到与Armadillo矩阵一起使用的示例。在我的情况下,定义Armadiilo矩阵的约简的最佳方法是什么?

1个回答

8

这些减少只适用于内置类型(doubleint等)。因此,您需要自己进行减少,这很简单。只需在线程本地变量中累积每个线程的结果,并在临界区域内将其添加到全局结果中。

#include <armadillo>
#include <omp.h>

int main()
{

  arma::mat A = arma::randu<arma::mat>(1000,700);
  arma::mat X = arma::zeros(700,700);
  arma::rowvec point = A.row(0);

  #pragma omp parallel shared(A)
  {
    arma::mat X_local = arma::zeros(700,700);

    #pragma omp for
    for(unsigned int i = 0; i < A.n_rows; i++)
    {
      arma::rowvec diff = point - A.row(i);
      X_local += diff.t() * diff; // Adding the matrices to X here
    }

    #pragma omp critical
    X += X_local;
  }
}

使用较新的OpenMP(我想是4.5吧?)您还可以为自己的类型声明用户定义的约简。

#include <armadillo>
#include <omp.h>

#pragma omp declare reduction( + : arma::mat : omp_out += omp_in ) \
  initializer( omp_priv = omp_orig )

int main()
{

  arma::mat A = arma::randu<arma::mat>(1000,700);
  arma::mat X = arma::zeros(700,700);
  arma::rowvec point = A.row(0);

  #pragma omp parallel shared(A) reduction(+:X)
  for(unsigned int i = 0; i < A.n_rows; i++)
  {
    arma::rowvec diff = point - A.row(i);
    X += diff.t() * diff; // Adding the matrices to X here
  }
}

谢谢。为什么在对X_local进行加法操作之前不需要关键字“critical”?我尝试了第二个答案,但是它给了我这个错误(我知道我的矩阵维度没有问题):“error: addition: incompatible matrix dimensions: 0x0 and 700x700 terminate called after throwing an instance of 'std::logic_error' what(): addition: incompatible matrix dimensions: 0x0 and 700x700 terminate called recursively Aborted (core dumped)” - Cauchy
@Cauchy (1) X_local 是每个线程本地的。指令 #pragma omp for 将 for 循环分成每个线程的分区,因此没有两个线程会写入相同的 X_local。(2) 是的,那是一个错误。我忘记了初始化程序,矩阵默认初始化为 0x0。请查看更新后的答案。 - Henri Menke
默认情况下,来自外部作用域的所有变量都作为共享变量进入并行区域(除了循环变量),因此您不必明确标记任何内容为共享。 - Henri Menke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接