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_commlocal_leader, 而对 remote_leaderlocal_leadertag 都不能使用通配符。注意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 中的组间通信方法, 在下一篇中我们将对组及通信子做一个简短的小结。

你可能感兴趣的:(mpi4py 中的组间通信)