MPI 中通信器之间的发送和接收操作

Send and Receive operations between communicators in MPI

接着我之前的问题:

MPI_INTERCOMM_CREATE的问题已经解决。但是当我尝试在颜色 0 的进程 0(全局等级 = 0)和颜色 1 的进程 0(即全局等级 = 2)之间实现基本的发送接收操作时,代码在打印接收缓冲区后挂断。 代码:

program hello
include 'mpif.h'
implicit none 
integer tag,ierr,rank,numtasks,color,new_comm,inter1,inter2
integer sendbuf,recvbuf,tag,stat(MPI_STATUS_SIZE)

tag = 22
sendbuf = 222

call MPI_Init(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD,numtasks,ierr)

if (rank < 2) then
color = 0
else 
color = 1
end if

call MPI_COMM_SPLIT(MPI_COMM_WORLD,color,rank,new_comm,ierr)

if (color .eq. 0) then
if (rank == 0) print*,' 0 here'
call MPI_INTERCOMM_CREATE(new_comm,0,MPI_Comm_world,2,tag,inter1,ierr)
call mpi_send(sendbuf,1,MPI_INT,2,tag,inter1,ierr)

!local_comm,local leader,peer_comm,remote leader,tag,new,ierr

else if(color .eq. 1) then
 if(rank ==2) print*,' 2 here'
call MPI_INTERCOMM_CREATE(new_comm,2,MPI_COMM_WORLD,0,tag,inter2,ierr)
call mpi_recv(recvbuf,1,MPI_INT,0,tag,inter2,stat,ierr)
print*,recvbuf
end if
end

互通的通信大部分用户理解的不是很好,例子也没有其他MPI操作的例子多。您可以按照 this link.

找到很好的解释

现在,有两件事要记住:

1) 内部通信器中的通信总是从一个组到另一个组。发送时,目的地的等级是其在远程组通信器中的本地等级。接收时,发送方的等级为其在远程群通信器中的本地等级。

2) 点对点通信(MPI_send 和 MPI_recv 系列)在一个发送者和一个接收者之间。在你的例子中,颜色0的每个人都在发送,颜色1的每个人都在接收,但是,如果我理解你的问题,你想要颜色0的过程0向颜色 1.

的进程 0 发送内容

发送代码应该是这样的:

call MPI_COMM_RANK(inter1,irank,ierr)
if(irank==0)then
    call mpi_send(sendbuf,1,MPI_INT,0,tag,inter1,ierr)
end if

接收代码应如下所示:

call MPI_COMM_RANK(inter2,irank,ierr)
if(irank==0)then
    call mpi_recv(recvbuf,1,MPI_INT,0,tag,inter2,stat,ierr)
    print*,'rec buff = ', recvbuf
end if

在示例代码中,有一个新的变量irank,我用它来查询inter-communicator中每个进程的排名;那是他本地通讯器中进程的等级。因此,您将有两个排名 0 的过程,每个组一个,依此类推。

重要的是要强调您的 post 的其他评论员所说的话:在那些现代构建程序时,使用像 use mpi 这样的现代结构而不是 include 'mpif.h' 见评论来自 Vladimir F。您之前的问题的另一个建议是,在这两种情况下,您都使用等级 0 作为远程领导者。如果我将这两个想法结合起来,您的程序可能如下所示:

program hello
use mpi !instead of include 'mpif.h'
implicit none

    integer :: tag,ierr,rank,numtasks,color,new_comm,inter1,inter2
    integer :: sendbuf,recvbuf,stat(MPI_STATUS_SIZE)
    integer :: irank
    !
    tag = 22
    sendbuf = 222
    !
    call MPI_Init(ierr)
    call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr)
    call MPI_COMM_SIZE(MPI_COMM_WORLD,numtasks,ierr)
    !
    if (rank < 2) then
        color = 0
    else 
        color = 1
    end if
    !
    call MPI_COMM_SPLIT(MPI_COMM_WORLD,color,rank,new_comm,ierr)
    !
    if (color .eq. 0) then
        call MPI_INTERCOMM_CREATE(new_comm,0,MPI_Comm_world,2,tag,inter1,ierr)
    !
    call MPI_COMM_RANK(inter1,irank,ierr)
    if(irank==0)then
        call mpi_send(sendbuf,1,MPI_INT,0,tag,inter1,ierr)
    end if
    !
    else if(color .eq. 1) then
        call MPI_INTERCOMM_CREATE(new_comm,0,MPI_COMM_WORLD,0,tag,inter2,ierr)
        call MPI_COMM_RANK(inter2,irank,ierr)
        if(irank==0)then
            call mpi_recv(recvbuf,1,MPI_INT,0,tag,inter2,stat,ierr)
            if(ierr/=MPI_SUCCESS)print*,'Error in rec '
            print*,'rec buff = ', recvbuf
        end if
    end if
    !
    call MPI_finalize(ierr)
end program h