如何解决关于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 举报,一经查实,本站将立刻删除。