【问题标题】:passing 3D arrays usnig MPI_ALLGATHERV传递 3D 数组 usnig MPI_ALLGATHERV
【发布时间】:2013-11-19 17:59:56
【问题描述】:

我正在尝试使用 MPI_ALLGATHERV 将 3D 数组传递给所有其他进程。 v1 是一个普通的块数组。

parameter (nprocz=48,nzro=1)
do 1 i=i101,i102
  do 2 j = je0, je1-1
  do 2  k = ke0, ke1
    v1(k,j,i) = v1(k,j,i)*0.015*float(i-iv0)
2    continue
1   continue      
nmpi01=floor((iv0-ie0-nzro)/(nprocz-1))
if (mpirank .le. nprocz-2) then
   i101=ie0+(mpirank*nmpi01)
   i102=ie0+(mpirank+1)*nmpi01-1
else
   i101=ie0+(mpirank*nmpi01)
   i102=iv0-1
endif
scount=(i102-i101+1)*(je1-je0)*(ke1-ke0+1)
rcount(mpirank+1)=scount
displs(mpirank+1)=mpirank*scount+1 call
MPI_ALLGATHERV(v1(1,1,i101),scount,MPI_REAL,v1(1,1,1)  ,rcount,displs,MPI_REAL,MPI_COMM_WORLD,ierr004)

但这个错误和我的进程一样多:

Fatal error in PMPI_Allgatherv: Internal MPI error!, error stack:
...
MPIR_Localcopy(378).......: memcpy arguments alias each other, dst=0x7ccddb44  
src=0x7ccddb40 len=3642752

然后我试了一下,MPI_IN_PLACE 是这样的:

 MPI_ALLGATHERV(MPI_IN_PlACE,scount,MPI_REAL,v1(1,1,1),   
 rcount,displs,MPI_REAL,MPI_COMM_WORLD,ierr004) 

但内存一直在递增使用,直到程序崩溃。

【问题讨论】:

    标签: arrays 3d mpi fortran77


    【解决方案1】:

    MPI_ALLGATHERV 要求每个等级指定通信器中每个等级的大小和位移。你做什么你只填写一个等级的值:

    rcount(mpirank+1)=scount
    displs(mpirank+1)=mpirank*scount+1
    

    相反,您应该遍历等级并计算每个等级中 rcountdispls 的所有元素:

    integer :: myscount, myi101
    
    displs(1) = 0
    do rank = 0, nprocz-1
       nmpi01=floor((iv0-ie0-nzro)/(nprocz-1))
       if (rank .le. nprocz-2) then
          i101=ie0+(rank*nmpi01)
          i102=ie0+(rank+1)*nmpi01-1
       else
          i101=ie0+(rank*nmpi01)
          i102=iv0-1
       endif
       scount=(i102-i101+1)*(je1-je0)*(ke1-ke0+1)
       rcount(rank+1)=scount
       if (rank .gt. 0) then
          displs(rank+1) = displs(rank) + rcount(rank)
       endif
       if (rank .eq. mpirank) then
          myscount = scount
          myi101 = i101
       end if
    end do
    
    scount = myscount
    i101 = myi101
    
    call mpi_allgatherv(...)
    

    还要注意displs 的计算方式可能是错误的。如果接收到的数据之间没有间隙,则应保持以下关系:displs(i) = sum(rcount(1:i-1))编辑:我已将上面的代码更改为正确计算displs 数组元素的代码。

    【讨论】:

    • 谢谢,它有效,但结果仍然错误。 1-在我的情况下,每个部分的结果都用于下一部分,尤其是在mpi_allgatherv之后。所以我需要在每个mpi_allgatherv之后添加mpi_barrier吗? 2-应该使用mpi_in_place 吗?考虑我只有一个 3d 数组v1,每个子数组v1(1,1,i) 是由某个过程计算的,我想将计算出的子数组放在同一数组的适当部分。 3- 我猜displs(i) = sum(rcount(1:i-1)) 不正确。实际上它应该是displs(i) = sum(rcount(1:i-1))+1 for i=>2,考虑到在fortran77中总是displs(1)=1
    • 所以,我更正了这一点:循环前displs(1)=1,循环内displs(rank+2)=rank*scount+1,循环后displs(nprocz+1)=0。我说的对吗?
    • 位移是数组开头之后的元素数量,因此displs(1) 应该为0。另外scount 取决于排名,您不能简单地将其乘以循环中的排名。
    • 1-i 更正为 displs(1)=0 并将 displs(rank+1)=rank*scount+1 更改为 displs(rank+2)=(rank+1)*scount。虽然比以前好,但仍然是错误的结果。 2-我不明白你的第二句话。 scount 当然取决于排名,这就是为什么我根据排名计算指数i101i102,然后根据它们找到scount。 3-除此之外,我不需要将scount 排除在循环之外,因为在使用mpi_in_placeparameters 时,scountsend type 将被忽略。我仍然很困惑是什么问题。
    • 即使在每个mpi_allgather 之前添加mpi_barrier 后问题仍然存在。
    猜你喜欢
    • 1970-01-01
    • 2013-08-14
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多