这是一个矩阵向量乘法的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为10×10,全部为1,invec为1,2,3,...10。所以outvec的元素应该是invec,55中元素的总和。如果我运行该代码的结合体/向量版本,那么outvec的每个元素都是1,而不是55。如果我把约简和向量放在一起,那么我得到了正确的答案,55。在我超过90个元素之前,这个方法一直在工作。当我到91时,outvec的每一个元素都应该等于4186。但是只有最后一个是,其余的都等于4095 (1到90之和)。随着元素数量的增加,值的变化和正确答案的偏差越来越大。
我显然不明白减薪是怎么回事。有人能解释吗?
发布于 2015-11-23 22:36:36
约简子句需要在发生约简的情况下处于循环状态,即向量循环。我还建议在这里使用“核”指令,因为“并行”将为这两个循环创建一个内核启动,而“内核”将为每个循环创建两个内核。
例如:
subroutine foo(n,matrix,invec,outvec)
integer n
real*8, intent(in) :: matrix(n,n)
real*8, intent(in) :: 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 kernels
!$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 gang
do j=1,n
tmpsclr = 0.d0
!$acc loop vector reduction(+:tmpsclr)
do i=1,n
tmpsclr = tmpsclr+tmpmat(j,i)
enddo
outvec(j) = tmpsclr
enddo
!$acc end kernels
!$acc update host(outvec)
end subroutine foo
% pgf90 -c -acc -Minfo=accel test2.f90
foo:
11, Generating create(matrix(:,:),invec(:),outvec(:))
15, Generating update device(outvec(:),tmpmat(:,:),invec(:),matrix(:,:))
20, Loop is parallelizable
22, Loop is parallelizable
Accelerator kernel generated
Generating Tesla code
20, !$acc loop gang, vector(4) ! blockidx%y threadidx%y
22, !$acc loop gang, vector(32) ! blockidx%x threadidx%x
28, Loop is parallelizable
Accelerator kernel generated
Generating Tesla code
28, !$acc loop gang ! blockidx%x
31, !$acc loop vector(128) ! threadidx%x
Sum reduction generated for tmpsclr
31, Loop is parallelizable
39, Generating update host(outvec(:))希望这能帮上忙,马特
https://stackoverflow.com/questions/33759802
复制相似问题