我有一个嵌套循环:( 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];
}
}
但它也没有解决问题。结果仍然不同。
答案 0 :(得分:2)
我对OpenMP不太熟悉,但在我看来,您的计算与订单无关。也就是说,内循环中的结果写入L[i][k]
,其中i
和k
是内循环的不变量。这意味着在内循环期间相同的值会被覆盖k
次,从而导致竞争条件。
此外,dummy
似乎在不同的线程之间共享,因此也可能存在竞争条件,除非你的pragma参数以某种方式阻止它。
总之,对我来说,如果你想要顺序执行给出的相同结果,内部循环中的计算必须以相同的顺序执行。因此,只有外环可以并行化。
答案 1 :(得分:2)
在您的并行版本中,您插入了一个不必要的(可能有害的)原子指令。一旦你宣布dummy
为减少变量,OpenMP就会停止线程干扰减少。我认为不必要的指令的主要影响是减慢代码的速度。
我看到你有另一个答案来解决你的结果的错误。但我注意到你似乎在每个外循环迭代结束时将dummy
设置为0
,如果你试图将它用作某种累加器,这似乎很奇怪,这就是减少条款提示。也许你想在内循环中减少到dummy
?
如果您在减少read this时遇到问题。
答案 2 :(得分:1)
结果的差异来自内部循环变量n
,它在线程之间共享,因为它是在omp pragma之外定义的。
澄清:
循环变量n
应该在omp pragma中声明,因为它应该是特定于线程的,例如for (int n = 0;.....)