首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >减少OpenACC

减少OpenACC
EN

Stack Overflow用户
提问于 2015-11-17 14:45:18
回答 1查看 970关注 0票数 0

这是一个矩阵向量乘法的Fortran子程序.在许多方面,这可能是老式的和低效的,但是现在我只是想让它与OpenACC指令一起工作,并且我正在试图弄清楚减少是如何工作的:

代码语言:javascript
复制
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

这段代码实际上给出了正确的结果。但是,当我在最后一个循环上尝试一组/向量组合时,如下所示:

代码语言:javascript
复制
!$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之和)。随着元素数量的增加,值的变化和正确答案的偏差越来越大。

我显然不明白减薪是怎么回事。有人能解释吗?

EN

回答 1

Stack Overflow用户

发布于 2015-11-23 22:36:36

约简子句需要在发生约简的情况下处于循环状态,即向量循环。我还建议在这里使用“核”指令,因为“并行”将为这两个循环创建一个内核启动,而“内核”将为每个循环创建两个内核。

例如:

代码语言:javascript
复制
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(:))

希望这能帮上忙,马特

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33759802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档