2016-08-24 37 views
1
program main 
use omp_lib 
implicit none 
integer :: n=8 
integer :: i, j, myid, a(8, 8), b, c(8) 

! Generate a 8*8 array A                       
!$omp parallel default(none), private(i, myid), &                 
!$omp shared(a, n)                        
myid = omp_get_thread_num()+1 
do i = 1, n 
    a(i, myid) = i*myid 
end do 
!$omp end parallel                        

! Array A                           
print*, 'Array A is' 
do i = 1, n 
print*, a(:, i) 
end do 

! Sum of array A                         
b = 0 
!$omp parallel reduction(+:b), shared(a, n), private(i, myid)              
myid = omp_get_thread_num()+1 
do i = 1, n 
    b = b + a(i, myid) 
end do 
!$omp end parallel                        
print*, 'Sum of array A by reduction is ', b 

b = 0 
c = 0 
!$omp parallel do                         
do i = 1, n 
    do j = 1, n 
     c(i) = c(i) + a(j, i) 
    end do 
end do 
!$omp end parallel do                        
print*, 'Sum of array A by using parallel do is', sum(c) 

!$omp parallel do                         
do i = 1, n 
    do j = 1, n 
     b = b + a(j, i) 
    end do 
end do 
!$omp end parallel do                        
print*, 'Sum of array A by using parallel do in another way is', b 

end program main 

我寫了一段Fortran代碼來實現OpenMP,以三種不同方式總結8 * 8數組中的所有元素。第一個使用減少和工作。其次,我創建了一個包含8個元素的一維數組。我在平行區域總結每一列,然後總結它們。這也適用。第三個我用一個整數來對數組中的每個元素進行總結,並且將它並行放入區域。這個結果是不正確的,每次都不一樣。我不明白爲什麼會出現這種情況。是因爲沒有指定public和private,或者變量b在程序中被覆蓋了嗎?並行在Fortran中出錯

+1

您可以通過指定減少(+:b)來糾正競態條件。 – tim18

+0

這段代碼似乎認爲有8個線程。如果你要在一臺不是真的大型機器上運行! (請注意,我*不*,建議您添加numthreads(8)條款,而是暗示任何像這樣的代碼,其中明確使用線程數是一個壞主意...) –

+0

是的,我定義了8個線程。我應該提到這一點。 – Yongxin

回答

5

有上b競爭條件上的第三種情況:多個線程讀,沒有適當的同步/私有化寫同一個變量。

請注意,您不必在第二種情況下的競爭條件:每個線程正在更新一些數據(即c(i)),沒有其他人正在訪問。

最後,你的最後一個場景的一些解決方案:

  1. reducion(+:b)條款添加到編譯
  2. b = b + c(j,i)表達之前添加pragma omp atomic指令
  3. 您可以實現手動私有化
+0

看來他在上一次循環中有相同的問題,其中b正在被所有線程讀取和更新。 – Jauch

+0

我指的是那一個,即計算A的總和其他兩個並行循環都很好 – smateo

+0

好吧,這就是你提到的B方案是第四,沒有第三種情況:) – Jauch