1.函数说明
MPI_Gatherv
MPI_Gatherv(
void* sendbuf,
int sendcnt,
MPI_Datatype sendtype,
void* recvbuf,
int recvcnts,
int* displs,
MPI_Datatype recvtype,
int root,
MPI_Comm comm)
收集不同长度的数据块。与MPI_Gather类似,但允许每个进程发送的数据块长度不同,并且根据进程可以任意排放数据块在recvbuf中的位置。recvbuf,recvtype,recvcnts和displs仅对根进程有意义。数组recvcnts和displs的元素个数等于进程数,用于指定从每个进程接收的数据块长度和他们在recvbuf中的位移,均以recvtype为单位。
MPI_Scatterv
MPI_Scatterv(
void* sendbuf,
int sendcnt,
int* displs,
MPI_Datatype sendtype,
void* recvbuf,
int recvcnts,
MPI_Datatype recvtype,
int root,
MPI_Comm comm)
散发不同长度的数据块,与MPI_Scatter类似,但允许sendbuf中每个数据块的长度不同并且可以按任意的顺序排放。sendbuf、sendtype、sendcnts和displs仅对根进程有意义。数组sendcnts和displs的元素个数等于comm中的进程数,它们分别给出发送给每个进程的数据长度和位移,均以sendtype为单位。
MPI参考手册
2.测试代码
mpi_scatterv_test.f90
PROGRAM Main
! -------------------------------------------
! MPI_Gatherv和MPI_Scatterv的Fortran测试代码
! Yuan @2020.05.19
! -------------------------------------------
IMPLICIT NONE
include 'mpif.h'
INTEGER :: prcnumb ! Total number of processes;
INTEGER :: myprcid ! Current process id,from 0 to prcnumb-1;
LOGICAL :: OnMonitor ! Whether it is a master node,0=True;
INTEGER :: num
INTEGER :: num_total
INTEGER :: i,ierr,count,root
INTEGER,DIMENSION(:),ALLOCATABLE :: num_n,lev,lev_n,displs
INTEGER,DIMENSION(:),ALLOCATABLE :: lev22
! ----------------------------
! 1.0 MPI初始化
! ----------------------------
CALL MPI_Init(ierr) !MPI环境初始化
CALL MPI_COMM_RANK(MPI_COMM_WORLD,myprcid,ierr) !获取当前进程id,从0开始编号
CALL MPI_COMM_SIZE(MPI_COMM_WORLD,prcnumb,ierr) !获取总进程数
OnMonitor=.false.
IF(myprcid==0) OnMonitor=.true.
! ----------------------------
! 2.0 MPI_Gather的测试例子
! ----------------------------
num=myprcid+1
PRINT*,'myprcid=',myprcid,'num=',num
ALLOCATE(num_n(1:prcnumb))
count=1
root=0 !主进程为0号进程
!Gather:收集相同长度的数据块
CALL MPI_Gather(num,count,mpi_integer4,num_n,count,mpi_integer4,root,MPI_COMM_WORLD,ierr)
! IF(OnMonitor) num_n(1)=num !将进程0的数据也收集到num_n
IF(OnMonitor) PRINT*,'Gather num result=',num_n
! ----------------------------
! 3.0 MPI_Gatherv的测试例子
! ----------------------------
ALLOCATE(lev(1:num))
lev=myprcid+1
PRINT*,'myprcid=',myprcid,'lev=',lev
IF(OnMonitor) THEN
num_total=sum(num_n)
PRINT*,'num_total=',num_total
ALLOCATE(lev_n(1:num_total))
ALLOCATE(displs(1:prcnumb))
DO i=1,prcnumb
displs(i)=sum(num_n(1:i-1)) !displs是相对位置,从0开始
ENDDO
PRINT*,'displs=',displs
ENDIF
!Gatherv:收集不同长度的数据块,num_n,displs,lev_n由root进程给出
CALL MPI_Gatherv(lev,num,mpi_integer4,lev_n,num_n,displs,mpi_integer4,root,MPI_COMM_WORLD,ierr)
IF(OnMonitor) PRINT*,'Gatherv lev result=',lev_n
! ----------------------------
! 3.1 MPI_Scatterv的测试例子
! ----------------------------
ALLOCATE(lev22(1:num))
CALL MPI_Scatterv(lev_n,num_n,displs,mpi_integer4,lev22,num,mpi_integer4,root,MPI_COMM_WORLD,ierr)
PRINT*,'myprcid=',myprcid,'lev22=',lev
! ----------------------------
! 4.0 释放空间及结束MPI并行环境
! ----------------------------
DEALLOCATE(lev)
IF(OnMonitor) DEALLOCATE(num_n,lev_n,displs)
CALL MPI_Finalize(ierr)
END PROGRAM Main
3.编译及运行结果
编译:
mpif90 -o test.exe mpi_scatterv_test.f90
mpirun -np 4 ./test.exe
结果:
测试代码运行结果.png