OpenMP 崩溃给出了错误的结果

OpenMP collapse gives wrong results

我有一个 3D 数组 z,其中每个元素的值都为 1

现在我这样做了:

#pragma omp parallel for collapse(3) shared(z)
for (int i=0; i < SIZE; ++i) {
    for (int j=0; j < SIZE; ++j) {
        for (int k=0; k < SIZE; ++k) {
            for (int n=0; n < ITERATIONS-1; ++n) {
                z[i][j][k] += 1;
            }
        }
    }
}

这应该将 ITERATIONS 添加到每个元素并且确实如此。如果我随后将 collapse(3) 更改为 collapse(4)(因为有 4 个 for 循环),我得不到正确的结果。

难道我不能折叠所有四个循环吗?

问题是第 4 个循环不能像第 3 个循环那样并行化。只是为了说服自己,只考虑最后一个循环。它将变成:

int zz = z[i][j][k];
for (int n=0; n < ITERATIONS-1; ++n) {
    zz += 1;
}
z[i][j][k] = zz;

为了并行化它,您需要添加一个 reduction(+:zz) 指令,对吗?
好吧,你的 collapse(4) 也有同样的故事。但是添加 reduction(+:z),如果可能的话,我不确定,会引发一些问题:

  1. 仅 OpenMP 4.5 及更高版本支持 C 或 C++ 中数组的 reduction 子句,目前我不知道有任何编译器支持它(尽管我确信有些编译器支持)。
  2. 由于管理减少方面的复杂机制,它可能无论如何都会使代码变慢。

所以底线是:根据需要坚持 collapse(3) 或更少,或者以不同的方式并行化循环。