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

C++ 使用omp并行使用引用的函数,c++,c++11,openmp,C++,C++11,Openmp,考虑简化的例子。假设我有以下功能: int foo(int x, int y, bool &flag) { if (x == y) flag = true; return x + y; } 然后使用openmp并行执行: bool flag = false; #pragma omp parallel for for (int i = 0; i < n; i++) { z[i] = foo(x[i], y[i], flag); } bool

考虑简化的例子。假设我有以下功能:

int foo(int x, int y, bool &flag) {
  if (x == y)
    flag = true;
  return x + y;
}
然后使用openmp并行执行:

  bool flag = false;

#pragma omp parallel for 
  for (int i = 0; i < n; i++) {
    z[i] = foo(x[i], y[i], flag);
  }
bool标志=false;
#pragma-omp并行
对于(int i=0;i
我猜这里的问题是函数被并行调用多次,并且每个实例都指向相同的
标志。使用相对简单的解决方案解决此问题的最佳方法是什么


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

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

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

解决方案是使用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];
  }
}
intmain(){
int常数n=4;
int x[n];
int y[n];
intz[n];
布尔标志=假;
#用于缩减的pragma omp并行(| |:标志)
对于(int i=0;i
每个线程现在都有自己的
标志的副本。在
parallel
块(即
for
循环)的末尾,将使用“or”减少本地副本,并将其放入线程全局变量
标志中


在其他情况下,您可以在
if
语句周围添加
#pragma omp critical
,但这会显著降低性能。

参考不是问题。问题在于数据竞争。即使代码是内联编写的,您也会得到它。@StoryTeller我不知道名称,但这正是我的意思。我认为重要的是要注意,您是将
标志作为函数的引用传递,还是直接在并行循环中使用它并不重要。@Zulan:的确,这是一个很好的观点。我已经把它添加到我的答案中。