2015-05-24 80 views
3

我一直在嘗試在兩個嵌套循環內的簡單求和操作上應用OpenMP,但到目前爲止產生了不正確的結果。我一直在環視herehere,也在here。所有建議使用reduction子句,但它不適用於我的情況,通過產生非常大的數字導致segmentation faultOpenMP over求和

我也試過這種方式貼在here和我自己的問題here已經解決了。兩者都不使用reduction,只是簡單地將總和變量設置爲shared,但它也會產生不正確的結果。有什麼我失蹤了嗎?何時使用reduction而不是在面對求和操作時使用它?使用reduction條款

代碼

index = 0 
!$OMP PARALLEL DO PRIVATE(iy,ix) REDUCTION(:+index) 
do iy = 1, number(2) 
    do ix = 1, number(1) 
     index = index + 1 
     xoutput(index)=xinput(ix) 
     youtput(index)=yinput(iy) 
    end do 
end do 
!$OMP END PARALLEL DO 

代碼,而無需使用reduction條款

index = 0 
!$OMP PARALLEL DO PRIVATE(iy,ix) SHARED(index) 
do iy = 1, number(2) 
    do ix = 1, number(1) 
     index = index + 1 
     xoutput(index)=xinput(ix) 
     youtput(index)=yinput(iy) 
    end do 
end do 
!$OMP END PARALLEL DO 
+0

它可能應該讀作還原(+:指數)'。 .. –

+0

在第二個版本中,'索引'在線程之間共享,'索引=索引+1'這一行導致競爭條件! –

回答

4

我認爲你必須的reduction條款做什麼誤概念...

REDUCTION(+:index) 

意味着,您將擁有正確的總和index最後。在迭代的每一步中,每個步驟都將具有不同的值,並具有不同的值!所以減少不適合在並行部分管理數組索引。

讓我試着說明這...

下面的循環

!$OMP PARALLEL DO PRIVATE(iy) REDUCTION(+:index) 
do iy = 1, number(2) 
    index = index + 1 
end do 
!$OMP END PARALLEL DO 

是(或多或少),相當於

!$OMP PARALLEL PRIVATE(iy, privIndex) SHARED(index) 
!$OMP DO 
do iy = 1, number(2) 
    privIndex = privIndex + 1 
end do 
!$OMP END DO 

!$OMP CRITICAL 
index = index + privIndex 
!$OMP END CRITICAL 
!$OMP END PARALLEL 

你可以看到,在循環過程中的所有線程對該線程專用的不同變量privIndex工作,並計算本地(部分)總和。最後,總金額爲critical,以避免競爭條件。

這可能不是編譯器所做的,但它讓你知道如何減少工作:在第一個循環中,沒有任何一點privIndex對應於串行版本中期望的正確索引。


正如普京建議在他的評論,你可以直接計算,你只在內部循環遞增它的指標:

!$OMP PARALLEL DO PRIVATE(iy,ix, index) 
do iy = 1, number(2) 
    do ix = 1, number(1) 
     index = (iy-1)*number(1) + ix 
     xoutput(index)=xinput(ix) 
     youtput(index)=yinput(iy) 
    end do 
end do 
!$OMP END PARALLEL DO 
+0

所以'reduce'作爲某種同步來確保循環結束時的求和值是正確的?我只是想確定一下,把'index'放在private中也是不正確的,不是嗎?因爲求和的值應該按順序不分佈在線程上? – Franky

+0

正如@AlexanderVogt所描述的那樣,縮減的工作原理正好相反,變量的私有副本在構造的末尾被減少。私人也沒有幫助,你會沒有同步,你會得到一些'索引'重複的值。 –

+1

@FrankyDjutanta爲什麼不從'ix'和'iy'計算'index'? –