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
接着我之前的问题:
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