mpi4py 中的组间通信
在上一篇中我们介绍了 mpi4py 中的通信子管理 API, 下面我们将介绍组间通信相关方法。
组间通信子对象在某些基于组内通信子对象的操作/访问函数中也可使用。
访问函数
MPI.Comm.Is_inter(self)
判断当前通信子是否是组间通信子。
MPI.Intercomm.Get_remote_size(self)
返回远程组包含的进程数。
MPI.Intercomm.Get_remote_group(self)
取得当前组间通信子的远程组对象。
构造与取消函数
组间通信的构造函数均为阻塞操作,并且要求所有本地组和远程组都不相交,否则将导致死锁。
MPI.Intracomm.Create_intercomm(self, int local_leader, Intracomm peer_comm, int remote_leader, int tag=0)
将两个组内通信子对象合并为组间通信子对象。要求两个组内通信子的本地组和远程组交集为空。此外,还要求至少各组内选中的两个 leader 进程能够实现通信,即两个 leader 至少要共同通过一个第三方 peer 通信子知道彼此 —— 知道彼此在 peer 通信子内的 rank 值(leader 可以是物理上的同一个进程)。在静态进程实现的 MPI 环境中,MPI.COMM_WORLD 通常可作为这个第三方的 peer 通信子。最后还要求各组内其它进程都能够知道本组 leader 的信息。实际执行这个操作时,在本地组和远程组执行集合操作,再加上两个组 leader 之间的点到点通信,因此两个组内的进程必须分别提供完全相同的 local_comm
和 local_leader
, 而对 remote_leader
,local_leader
和 tag
都不能使用通配符。注意:local_leader
是选定的本地组的进程的 rank 编号,而 remote_leader
则是选定的远程组的进程在 peer_comm
中的 rank 编号。
MPI.Intercomm.Merge(self, bool high=False)
将两个组间通信子对象合并为组内通信子对象。要求各组内进程提供完全相同的 high
参数值。如果一个组内的所有进程指定的 high
为 True 而另一个组所有进程指定的 high
为 False,则在新的组内通信子内 True 组的进程排在 False 组的进程前面。如果两个组内进程指定的 high
值相同,则排列顺序不确定。
下面给出组间通信的使用例程。
# inter_comm.py
import numpy as np
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
print 'Is MPI.COMM_WORLD a inter-communicator:', comm.Is_inter()
# split comm into two new communicators according to `color`
color = rank % 2
comm_split = comm.Split(color=color, key=rank)
if color == 0:
# create an inter-communicator by using rank 0 of local_comm and rank 1 of MPI.COMM_WORLD
comm_inter = comm_split.Create_intercomm(0, comm, 1, tag=12)
if comm_inter.rank == 0:
# rank 0 of local_comm sends a message to rank 1 of the remote_comm
send_obj = {'a': 1}
comm_inter.send(send_obj, dest=1, tag=1)
print 'rank %d of comm_inter with color 0 sends %s...' % (comm_inter.rank, send_obj)
elif color == 1:
# create an inter-communicator by using rank 0 of local_comm and rank 0 of MPI.COMM_WORLD
comm_inter = comm_split.Create_intercomm(0, comm, 0, tag=12)
if comm_inter.rank == 1:
# rank 1 of local_comm receives a message from rank 0 of the remote_comm
recv_obj = comm_inter.recv(source=0, tag=1)
print 'rank %d of comm_inter with color 1 receives %s...' % (comm_inter.rank, recv_obj)
print 'Is comm_inter a inter_communicator:', comm_inter.Is_inter()
# merge the two inter-communicators
if color == 0:
high = True
elif color == 1:
high = False
comm_merge = comm_inter.Merge(high=high)
print 'rank %d in MPI.COMM_WORLD -> rank %d in comm_merge' % (rank, comm_merge.rank)
运行结果如下:
$ mpiexec -n 4 python inter_comm.py
Is MPI.COMM_WORLD a inter-communicator: False
Is MPI.COMM_WORLD a inter-communicator: False
Is MPI.COMM_WORLD a inter-communicator: False
Is MPI.COMM_WORLD a inter-communicator: False
Is comm_inter a inter_communicator: True
rank 2 in MPI.COMM_WORLD -> rank 3 in comm_merge
Is comm_inter a inter_communicator: True
rank 1 in MPI.COMM_WORLD -> rank 0 in comm_merge
rank 1 of comm_inter with color 1 receives {'a': 1}...
Is comm_inter a inter_communicator: True
rank 3 in MPI.COMM_WORLD -> rank 1 in comm_merge
rank 0 of comm_inter with color 0 sends {'a': 1}...
Is comm_inter a inter_communicator: True
rank 0 in MPI.COMM_WORLD -> rank 2 in comm_merge
上面我们介绍了 mpi4py 中的组间通信方法, 在下一篇中我们将对组及通信子做一个简短的小结。