我有一个 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)
,如果可能的话,我不确定,会引发一些问题:
- C 或 C++ 中数组的
reduction
子句仅在 OpenMP 4.5 及更高版本中受支持,目前我不知道有任何编译器支持它(尽管我确信有些编译器支持) . - 由于管理缩减方面的复杂机制,它可能无论如何都会使代码变慢。
所以底线是:只要坚持 collapse(3)
或根据需要减少,或者以不同的方式并行化循环。
关于c++ - OpenMP 崩溃给出了错误的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36542712/