如何在与OpenMP并行化的嵌套for循环中写入共享数组(通过指针)会产生错误的结果?

时间:2012-08-15 19:48:03

标签: c++ openmp

我有一个非常奇怪的问题,我试图解决和理解。我有一个以下形式的嵌套for循环:

#pragma omp parallel for schedule(guided) shared(Array) collapse(3)
for (int i=istart; i<iend; i++)
{
  for (int j=jstart; j<jend; j++)
  {
    for(int k=kstart; k<kend; k++)
    {
       Int IJK = (i*(jend-jstart) + (j-jstart))*(kend-kstart) + (k-kstart);
       Array[3*IJK + 2] = an operation with some shared values;
    }
  }
}

此表单有三个循环,分别为Array[3*IJK]Array[3*IJK + 1]Array[3*IJK+2]。 Array实际上也是一个共享指针,对于IJK的值,实际上调用了一个函数(内联)。

我首先尝试并行化所有循环并且程序运行,但结果与我的序列结果相比有所不同。

现在来了奇怪的部分。

具有相同结构但具有Array[3*IJK + 1]的for循环在并行化时会产生正确的结果(在这种情况下其他循环是串行的)。但是当我并行化其他循环之一时,我会得到不同的结果。只有这个单循环在自身并行化时才能产生正确的结果。

另外,如果我不使用collapsecollapse(2)代替collapse(3),我会得到不同的结果。只有使用上面的#pragma语句,我才能在Array[3*IJK + 1]循环中获得正确的结果。

我认为它可能与编写Array的顺序有关,但是使用有序的子句和构造,我仍然得到错误的结果。

这可能是什么原因?

1 个答案:

答案 0 :(得分:0)

您确定您的连续案例是否正确?

您的IJK计算对我没有意义;首先,它完全不依赖于j。实际上,如果两个线程获得相同的(i,k)对具有不同的j - 当然可能与collapse(3) - 将会出现竞争条件,因为它们都将尝试写入相同的IJK 。

你确定你不想要像

这样的东西
   Int IJK = (i*(jend-jstart) + (j-jstart))*(kend-kstart) + (k-kstart);