连续和并行版本会产生不同的结果 - 为什么?
我有一个嵌套的循环:(L和A完全定义输入)连续和并行版本会产生不同的结果 - 为什么?
#pragma omp parallel for schedule(guided) shared(L,A) \
reduction(+:dummy)
for (i=k+1;i<row;i++){
for (n=0;n<k;n++){
#pragma omp atomic
dummy += L[i][n]*L[k][n];
L[i][k] = (A[i][k] - dummy)/L[k][k];
}
dummy = 0;
}
而其串行版本:
for (i=k+1;i<row;i++){
for (n=0;n<k;n++){
dummy += L[i][n]*L[k][n];
L[i][k] = (A[i][k] - dummy)/L[k][k];
}
dummy = 0;
}
他们都得到不同的结果。并行版本比顺序版本慢得多。
什么可能导致问题?
编辑:
为了摆脱引起的原子指令的问题,我修改了代码如下:
#pragma omp parallel for schedule(guided) shared(L,A) \
private(i)
for (i=k+1;i<row;i++){
double dummyy = 0;
for (n=0;n<k;n++){
dummyy += L[i][n]*L[k][n];
L[i][k] = (A[i][k] - dummyy)/L[k][k];
}
}
但它也没有工作出了问题。结果仍然不同。
结果的差异来自线程间共享的内部循环变量n
,因为它是在omp编译指示之外定义的。
澄清: 循环变量n
应OMP编译内部声明,因为它应该是线程专用的,例如for (int n = 0;.....)
完全解决了我的问题。谢谢! – 2012-04-07 10:54:20
@Lubo,那么正确的方法是什么? – 2013-09-28 13:12:20
我对OpenMP并不是很熟悉,但在我看来,您的计算并不依赖于顺序。也就是说,内循环中的结果写入L[i][k]
,其中i
和k
是内循环的不变量。这意味着在内循环期间相同的值被覆盖k
次,导致竞争条件。
此外,dummy
似乎在不同的线程之间共享,所以也可能存在竞争条件,除非您的编译指示参数以某种方式阻止它。
总而言之,对于我来说,如果您希望获得与顺序执行相同的结果,则内部循环中的计算必须以相同的顺序执行。因此只有外部环路可以并行化。
我也考虑过这个问题。但是使用这些编译指令,只有外部循环应该被并行化。但显然,线程内部正在发生其他事情,所以结果并不相同。 – 2012-04-07 08:45:13
在您的并行版本中,您插入了不必要的(可能有害的)原子指令。一旦你声明dummy
是一个缩减变量,OpenMP负责停止干扰缩减的线程。我认为这个不必要的指令的主要影响是减慢你的代码,很多。
我看到你有另一个解决你的结果错误的答案。但我注意到,在每个外循环迭代结束时,您似乎将dummy
设置为0
,如果您尝试将它用作某种累加器,这似乎很奇怪,这就是还原子句所暗示的内容。也许你想在内循环中减少到dummy
?
如果您在还原时遇到问题read this。
我实际上想要内循环在每个线程中顺序运行。我现在假设内部循环也是分布式的 - 否则我不会遇到这些问题。 我稍微修改了代码。我编辑过,以便您可以看到修改。 – 2012-04-07 08:50:14
如果您在浮点数操作,请阅读此http://计算器.com/a/8991640/893693 – inf 2012-04-07 08:21:46