使用omp并行使用引用的函数

Tim*_*Tim 2 c++ openmp c++11

考虑简化的例子.说我有以下功能:

int foo(int x, int y, bool &flag) {
  if (x == y)
    flag = true;
  return x + y;
}
Run Code Online (Sandbox Code Playgroud)

然后使用openmp并行执行:

  bool flag = false;

#pragma omp parallel for 
  for (int i = 0; i < n; i++) {
    z[i] = foo(x[i], y[i], flag);
  }
Run Code Online (Sandbox Code Playgroud)

我想这里的问题是函数被并行调用多次,每个实例都指向相同的flag.使用一些比较简单的解决方案解决这个问题的最佳方法是什么?

免责声明:我知道很多人会说以这种方式使用引用是不好的,但在我的情况下,它是实现任务的最简单方法:标记是否发生任何异常.

Mar*_*ing 5

这会给你一场比赛.在这种特殊情况下,您可能没有问题,因为线程只会在一个方向上更改变量,因此如果两个线程同时在其上写入,则最终结果将是相同的.但这仍然很糟糕.

引用不是问题,当您不调用外部函数时,您会遇到同样的问题.在我的下面的例子中,我不会使用外部函数,但这不会改变要点.

解决方案是使用OpenMP减少:

int main() {
  int const n = 4;
  int x[n];
  int y[n];
  int z[n];

  bool flag = false;
#pragma omp parallel for reduction(|| : flag)
  for (int i = 0; i < n; i++) {
    if (x[i] == y[i])
      flag = true;
    z[i] = x[i] + y[i];
  }
}
Run Code Online (Sandbox Code Playgroud)

每个线程现在都有自己的副本flag.在parallel块的末尾,即for循环,将使用"或"减少本地副本,并将其放入线程全局变量中flag.

在其他情况下,您可以放置#pragma omp criticalif声明,但这会显着降低您的性能.

  • 我认为重要的是要注意,无论是传递`flag`作为函数的引用还是直接在并行循环中使用它都无关紧要. (2认同)