這裏是矩陣向量乘法的Fortran子程序。這可能是老式的和低效的多種方式,但現在我只是想獲得它OpenACC的指令來工作,我試圖找出減少是如何工作的:OpenACC中的減少
subroutine matrmult(matrix,invec,outvec,n)
integer:: n
real*8, intent(in):: matrix(n,n), invec(n)
real*8, intent(out) :: outvec(n)
real*8 :: tmpmat(n,n)
real*8 :: tmpscl
integer :: i,j,k
!$acc declare create(matrix, invec, outvec, tmpmat)
outvec = 0.d0
!$acc update device(matrix, invec, tmpmat, outvec)
!$acc parallel
!$acc loop gang
do j=1,n
!$acc loop vector
do i=1,n
tmpmat(i,j) = matrix(i,j)*invec(j)
enddo
enddo
!$acc loop vector reduction(+:tmpsclr)
do j=1,n
tmpsclr = 0.d0
do i=1,n
tmpsclr = tmpsclr+tmpmat(j,i)
enddo
outvec(j) = tmpsclr
enddo
!$acc end parallel
!$acc update host(outvec)
end subroutine
這代碼實際上給出正確的結果但是,當我試圖在最後循環幫會/矢量組合,就像這樣:
!$acc loop gang reduction(+:tmpsclr)
do j=1,n
tmpsclr = 0.d0
!$acc loop vector
do i=1,n
tmpsclr = tmpsclr+tmpmat(j,i)
enddo
outvec(j) = tmpsclr
enddo
結果回來都錯了。對於outvec
的大多數(但不是全部)元素,總看起來不完整。無論我在哪裏放置reduction
條款,無論是在幫派還是向量中,都是如此。改變位置會改變結果,但從不會給出正確的結果。
我在一個簡單的測試中得到的結果如下所示。 matrix
是10x10和全1,而invec
是1,2,3,... 10。所以outvec
的元素應該只是invec
,55中元素的總和。如果我運行代碼的gang/vector版本,outvec
的每個元素都是1,而不是55.如果我用向量進行縮減,好吧,然後我得到正確的答案,55.並且這繼續工作,直到我得到90個元素。當我達到91時,outvec
的每個元素應該等於4186.但是隻有最後一個元素是,而其餘所有元素都等於4095(1到90之和)。隨着元素數量越來越大,值的變化以及與正確答案的差異越來越大。
我顯然不明白減法是如何工作的。誰能解釋一下?
@Vladimir˚F請參閱我的編輯。謝謝。 –