【发布时间】:2022-01-10 18:28:00
【问题描述】:
我正在尝试学习如何使用以下玩具代码执行 GPU 间数据通信。该程序的任务是将 gpu-0 中的数组“a”数据发送到 gpu-1 的内存中。我采取了以下根来这样做,这涉及四个步骤:
在 gpu0 上初始化数组 'a' 后,
- step1:将数据从gpu0发送到cpu0(使用
!acc update self()子句) - step2:从cpu0向cpu1发送数据(使用
MPI_SEND()) - step3:从cpu0接收数据到cpu1(使用
MPI_RECV()) - step4:更新gpu1设备内存(使用
!$acc update device()子句)
这工作得很好,但这看起来像是一条很长的路,我认为有更好的方法来做到这一点。我尝试阅读以下帖子中建议的!$acc host_data use_device 子句,但无法实施:
Getting started with OpenACC + MPI Fortran program
我想知道如何使用!$acc host_data use_device 以有效地执行下面显示的任务。
PROGRAM TOY_MPI_OpenACC
implicit none
include 'mpif.h'
integer :: rank, nprocs, ierr, i, dest_rank, tag, from
integer :: status(MPI_STATUS_SIZE)
integer, parameter :: N = 10000
double precision, dimension(N) :: a
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,nprocs,ierr)
print*, 'Process ', rank, ' of', nprocs, ' is alive'
!$acc data create(a)
! initialize 'a' on gpu0 (not cpu0)
IF (rank == 0) THEN
!$acc parallel loop default(present)
DO i = 1,N
a(i) = 1
ENDDO
ENDIF
! step1: send data from gpu0 to cpu0
!$acc update self(a)
print*, 'a in rank', rank, ' before communication is ', a(N/2)
IF (rank == 0) THEN
! step2: send from cpu0
dest_rank = 1; tag = 1999
call MPI_SEND(a, N, MPI_DOUBLE_PRECISION, dest_rank, tag, MPI_COMM_WORLD, ierr)
ELSEIF (rank == 1) THEN
! step3: recieve into cpu1
from = MPI_ANY_SOURCE; tag = MPI_ANY_TAG;
call MPI_RECV(a, N, MPI_DOUBLE_PRECISION, from, tag, MPI_COMM_WORLD, status, ierr)
! step4: send data in to gpu1 from cpu1
!$acc update device(a)
ENDIF
call MPI_BARRIER(MPI_COMM_WORLD, ierr)
print*, 'a in rank', rank, ' after communication is ', a(N/2)
!$acc end data
call MPI_BARRIER(MPI_COMM_WORLD, ierr)
END
编译:mpif90 -acc -ta=tesla toycode.f90(来自 nvidia hpc-sdk 21.9 的 mpif90)
执行:mpirun -np 2 ./a.out
【问题讨论】:
标签: fortran mpi openacc nvidia-hpc-compilers