[英]Sequential and parallel versions give different results - Why?
我有一個嵌套循環:(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];
}
}
但它也沒有解決問題。 結果還是不一樣。
我對 OpenMP 不太熟悉,但在我看來,您的計算與順序無關。 即,將內循環的結果寫入L[i][k]
,其中i
和k
是內循環的不變量。 這意味着同一值在內循環中被覆蓋k
次,從而導致競爭條件。
此外, dummy
似乎在不同線程之間共享,因此那里也可能存在競爭條件,除非您的 pragma 參數以某種方式阻止它。
總之,在我看來,如果您想要順序執行給出的結果相同,則內部循環中的計算必須以相同的順序執行。 因此只有外部循環可以並行化。
在您的並行版本中,您插入了一個不必要的(並且可能有害的)原子指令。 一旦您將dummy
聲明為縮減變量,OpenMP 就會負責停止干擾縮減的線程。 我認為不必要的指令的主要影響是大大降低了代碼速度。
我看到您有另一個解決結果錯誤的答案。 但是我注意到你似乎在每次外循環迭代結束時將dummy
設置為0
,如果你試圖將它用作某種累加器,這似乎很奇怪,這就是 reduction 子句所建議的。 也許您想減少內部循環的dummy
?
如果您在還原方面遇到問題,請閱讀此。
結果的差異來自內部循環變量n
,它在線程之間共享,因為它是在 omp pragma 之外定義的。
澄清:循環變量n
應該在 omp pragma 中聲明,因為它應該是特定於線程的,例如for (int n = 0;.....)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.