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

How can writing to a shared array (over a pointer) in a nested for loop parallelized with OpenMP produce wrong results?

本文关键字:指针 结果 错误 何产生 数组 共享 嵌套 并行 OpenMP for 循环      更新时间:2023-10-16

我有一个非常奇怪的问题,我试图解决和理解。我有一个以下形式的嵌套 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]。数组实际上也是一个共享指针,对于 IJK 的值,实际上调用了一个函数(内联)。

我首先尝试并行化所有循环,程序贯穿始终,但与我的串行结果相比,结果不同。

现在奇怪的部分来了。

具有

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

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

我认为这可能与Array的写入顺序有关,但是对于有序子句和构造,我仍然得到错误的结果。

这是什么原因造成的?

你确定你的连环案例是正确的吗?

你的IJK计算对我来说毫无意义;首先,它根本不取决于j。 事实上,如果两个线程获得具有不同 j 的相同 (i,k) 对 - 当然可能使用 collapse(3) - 将存在竞争条件,因为它们都将尝试写入相同的 IJK。

确定你不想要这样的东西吗

   Int IJK = (i*(jend-jstart) + (j-jstart))*(kend-kstart) + (k-kstart);