减少OpenACC

时间:2015-11-17 14:45:18

标签: cuda fortran reduction openacc

这是一个用于矩阵向量乘法的Fortran子程序。它可能在很多方面都是过时的和低效的,但是现在我只是试图让它与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的总和)。随着元素数量的增加,值的变化和与正确答案的差异变得更糟。

我显然不明白减少是如何运作的。谁能解释一下?

0 个答案:

没有答案