微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于acc例程的一些问题

如何解决关于acc例程的一些问题

一个 MPI 代码,我试图将它的一个简单循环与 openacc 并行化,但不期望输出在这里,循环有一个调用,我在子例程中添加一个“acc 例程 seq”。如果我手动进行内联调用删除子程序,结果将是正确的。我是否正确使用 OpenACC“例程”指令?还是其他错误

  • 运行时环境

MPI 版本:openmpi4.0.5
性能计算 SDK 20.11
CUDA 版本:10.2

!The main program
program test
  use simple
  use mpi
  implicit none
  integer :: i,id,size,ierr,k,n1
  call MPI_INIT(ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD,ierr)
  call MPI_COMM_SIZE(MPI_COMM_WORLD,ierr)

  allocate(type1(m))
  do i=1,m
    allocate(type1(i)%member(n))
    type1(i)%member=-1
    type1(i)%member(i)=i
  enddo
  
  !$acc update device(m,n)
  do k=1,m
    n1=0
    allocate(dev_mol(k:2*k))
    dev_mol=type1(k)%member(k:2*k)
    !$acc update device(dev_mol(k:2*k))
    !$acc parallel copy(n1) firstprivate(k)
    !$acc loop independent
    do i=k,2*k
      call test1(k,n1,i)
    enddo
    !$acc end parallel
    !$acc update self(dev_mol(k:2*k))
    type1(k)%member(k:2*k)=dev_mol
    write(*,"('k=',I3,' n1=',I2)") k,n1
    deallocate(dev_mol)
  enddo
  
  do i=1,m
    write(*,"('i=',I2,' member=',I3)") i,type1(i)%member(i)
    deallocate(type1(i)%member)
  enddo
  deallocate(type1)
  call MPI_Barrier(MPI_COMM_WORLD,ierr)
  call MPI_Finalize(ierr)
end


!Here is the module
module simple
  implicit none
  integer :: m=5,n=2**15
  integer,parameter :: p1=15
  integer,allocatable :: dev_mol(:)
  type type_related
    integer,allocatable :: member(:)
  end type
  type(type_related),allocatable :: type1(:)
  
  !$acc declare create(m,n,dev_mol)
  !$acc declare copyin(p1)
  contains
    subroutine test1(k,i)
      implicit none
      integer :: k,i
      !$acc routine seq
      if(dev_mol(i)>0) then
        !write(*,*) 'gpu',i
        n1=dev_mol(i)
        dev_mol(i)=p1
      else
        if(i==k)write(*,*) 'err',i,dev_mol(i)
      endif
    end
end
  • MPI

编译命令:mpif90 test.f90 -o test
运行命令:mpirun -n 1 ./test
结果如下:

k=  1 n1= 1
k=  2 n1= 2
k=  3 n1= 3
k=  4 n1= 4
k=  5 n1= 5
i= 1 member= 15
i= 2 member= 15
i= 3 member= 15
i= 4 member= 15
i= 5 member= 15
  • MPI+OpenACC

编译命令:mpif90 test.f90 -o test -ta=tesla:cuda10.2 -Minfo=accel
运行命令:mpirun -n 1 ./test
错误结果如下:

k=  1 n1= 0
k=  2 n1= 0
k=  3 n1= 0
k=  4 n1= 0
k=  5 n1= 0
i= 1 member= 1
i= 2 member= 2
i= 3 member= 3
i= 4 member= 4
i= 5 member= 5

解决方法

问题在于“i”是通过引用传递的(Fortran 的默认设置)。最简单的解决方案是按值传递:

  contains
    subroutine test1(k,n1,i)
      implicit none
      integer,value :: i
      integer :: n1,k

现在有一个小的编译器错误,因为“i”是循环索引变量,所以应该隐式地私有化变量。然而,由于它是通过引用传递的,这会导致它被共享。我们将在未来的编译器版本中修复此问题。尽管在可能的情况下按值传递标量通常是可取的。

使用更新运行的示例:

% mpif90 test2.f90 -acc -Minfo=accel -V21.2 ; mpirun -np 1 a.out
test1:
     16,Generating acc routine seq
         Generating Tesla code
test:
     48,Generating update device(m,n)
     53,Generating update device(dev_mol(k:k*2))
     54,Generating copy(n1) [if not already present]
         Generating Tesla code
         56,!$acc loop gang,vector(128) ! blockidx%x threadidx%x
     60,Generating update self(dev_mol(k:k*2))
k=  1 n1= 1
k=  2 n1= 2
k=  3 n1= 3
k=  4 n1= 4
k=  5 n1= 5
i= 1 member= 15
i= 2 member= 15
i= 3 member= 15
i= 4 member= 15
i= 5 member= 15

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。