【问题标题】:Send and Receive operations between communicators in MPIMPI 中通信器之间的发送和接收操作
【发布时间】:2016-11-19 13:51:21
【问题描述】:

在我之前的问题之后:Unable to implement MPI_Intercomm_create

已解决 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

【问题讨论】:

  • 我只是快速浏览了一下代码,所以它可能有更多问题,但显然你在这里遇到了问题:call mpi_recv(recvbuf,1,MPI_INT,0,tag,inter1,stat,ierr) 因为这应该使用inter2 而不是inter1
  • 对所有 Fortran 问题使用标签 fortran。更多的人会看到它。 Fortran 90 只是该语言的一种旧版本。一个建议:在 Fortran 90 和更新版本中,最好使用 use mpi 而不是 include 'mpif.h'
  • 你也不要使用implicit none(你真的应该使用它!)并且你没有在任何地方声明stat。要么将其正确声明为数组,要么只使用MPI_STATUS_IGNORE
  • 编辑:在 mpi_recv 中使用 inter2,声明为 stat。问题仍然存在。
  • 状态呢?它没有在上面声明,所以你的代码不能被编译。

标签: parallel-processing fortran mpi openmpi


【解决方案1】:

大多数用户对互通的通信不太了解,示例不如其他MPI操作的示例多。你可以关注this link找到一个很好的解释。

现在,有两件事要记住:

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

2) 点对点通信(MPI_send 和 MPI_recv 系列)是在一个发送者和一个接收者之间。在您的情况下,颜色0 的每个人都在发送,而颜色1 的每个人都在接收,但是,如果我理解您的问题,您希望颜色0 的进程0 向进程@987654326 发送一些东西@颜色1

发送代码应该是这样的:

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中的rank;那是他本地通讯器中进程的排名。因此,您将有两个等级为0 的过程,每个组一个,依此类推。

重要的是要强调您帖子的其他评论员所说的话:在那些现代构建程序时,使用现代构造,如 use mpi 而不是 include 'mpif.h' 请参阅 Vladimir F 的评论。您之前问题的另一个建议在这两种情况下,您是否都使用 rank 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

【讨论】:

    猜你喜欢
    • 2015-07-09
    • 2013-04-15
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 2018-03-12
    • 2013-12-20
    • 2016-06-15
    • 2012-03-13
    相关资源
    最近更新 更多