我正在尝试在Fortran中实现一个MPI_intercomm
在两个交互器之间,一个具有前2个进程,另一个具有其余的进程。
我需要在新创建的通信器之间执行send,recv操作。
代码:
program hello
include 'mpif.h'
integer tag,ierr,rank,numtasks,color,new_comm,inter1,inter2
tag = 22
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,1,tag,inter1,ierr)
!local_comm,local leader,peer_comm,remote leader,tag,new,ierr
else if(color .eq. 1) then
call MPI_INTERCOMM_CREATE(new_comm,1,MPI_COMM_WORLD,0,tag,inter2,ierr)
end if
select case (color)
case (0)
call MPI_COMM_FREE(inter1)
case(1)
call mpi_comm_free(inter2)
end select
call MPI_finalize(ierr)
end
代码编译没有任何问题。但是在跑步时卡住了,有时会出现错误。
答案 0 :(得分:3)
简短回答:问题来自remote_leader
。
答案很长:
我假设您的分裂逻辑是您想要的:处理颜色0
中的0和1以及颜色1
的世界其他地方,并且您将始终拥有3个以上的进程。
你必须选择:
每种颜色的local_leader
。这是每个组领导者的本地沟通者(在您的案例中为new_comm
)中的排名。无头痛的方法是选择等级0的过程,因为这是本地通信器中的等级,所有过程都可以具有完全相同的值。所以我选择等级0。
每种颜色的remote_leader
;这必须是交流员另一端领导者的peer_comm
(在您的情况下为MPI_Comm_world
)中的排名。这意味着,颜色0的过程必须知道0
中颜色1
中的MPI_Comm_world
对应的进程;和颜色处理1必须知道0
中颜色0
中的哪个处理MPI_Comm_world
对应。根据您的分裂逻辑和选择本地领导者的逻辑,remote_leader
必须为颜色0处理2
,并为颜色0
处理1
。
你应该很好地使用这些修改过的代码行:
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)
else if(color .eq. 1) then
if(rank==2) print*, ' 2 here'
call MPI_INTERCOMM_CREATE(new_comm,0,MPI_COMM_WORLD,0,tag,inter2,ierr)
end if
与您的代码最重要的区别是,remote_leader
对于颜色2
是0
。这是问题的根源。
次要的区别在于{1}}对于颜色1是local_leader
。这与我选择0
的逻辑相对应。这不是问题的根源,但是,如果您只有local_leader
彩色1
处理,那就可以了。
感谢Hristo Iliev,我正在添加此更新。如果您的目标是将颜色1的流程1用作1
,那么颜色local_leader
的{{1}}应为remote_leader
,代码将为:
0
请确保检查此选项的所有内容,因为我没有特别注意检查它。另外,请确保您总是拥有3
彩色if (color .eq. 0) then
if(rank==0) print*, ' 0 here'
call MPI_INTERCOMM_CREATE(new_comm,0,MPI_Comm_world,3,tag,inter1,ierr)
else if(color .eq. 1) then
if(rank==2) print*, ' 2 here'
call MPI_INTERCOMM_CREATE(new_comm,1,MPI_COMM_WORLD,0,tag,inter2,ierr)
end if
进程。