也许最优雅的解决方案是让 Python 代码成为 MPI 应用程序的一部分。然后它将能够直接将数据(通过 MPI 消息)发送到 MPI 应用程序的其余部分,因为它将是 MPI 应用程序的一部分。这里有两种不同的方法:
1) 将 Python 二进制文件作为 0 级插入 MPI 作业。为了将其排除在集体操作的参与mpibinary
之外,您必须制作一个排除 0 级的子通信器,并将其用于所有进一步的集体通信mpibinary
。第一步是简单的部分。在 Open MPI 中,您将执行以下操作:
mpirun --hostfile hosts -np 1 pythonbinary args : -np 32 mpibinary args
这称为 MPMD(多程序多数据)启动,它将启动其中的一个副本,pythonbinary
该副本将成为 0 级,32 个副本mpibinary
将成为 1 级、2 级,......直到 32 级(总共 33 个进程) . 其他 MPI 实现也为 MPMD 启动提供了非常相似的机制。然后,您将使用MPI_Comm_split()
它来创建一个不包含 Python 程序的新通信器。拆分通信器是一项集体操作。这就是为什么您必须在 Python 代码和 C++ 应用程序中都调用它的原因。MPI_Comm_split()
取一个“颜色”和一个键,根据颜色的不同将通信器拆分为多个子通信器。然后根据键值对具有相同颜色的进程进行排序。您很可能希望这样称呼它:
在 Python 中:
python_comm = mpi.mpi_comm_split(mpi.MPI_COMM_WORLD, 0, 0)
在 C++ 中:
int rank;
MPI_Comm c_comm;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_split(MPI_COMM_WORLD, 1, rank, &c_comm);
通过使用rank
as key one 可以保证 in 中的进程顺序与c_comm
拆分之前的顺序相同,即 rank 1 fromMPI_COMM_WORLD
将变为 rank 0 in c_comm
, rank 2 将变为 rank 1 等。
从现在开始,C++ 应用程序可以c_comm
像往常一样用来执行集体操作。为了在 Python 和 C++ 代码之间进行通信,您仍然必须使用MPI_COMM_WORLD
Python 代码在其中的排名仍然为 0。
2) 使用 MPI-2 过程管理工具。首先,您将运行一个仅包含 Python 二进制文件的 MPI 作业:
mpirun --hostfile hosts -np 1 pythonbinary args
然后 Python 二进制文件将直接使用MPI_Comm_spawn()
所需数量的新进程生成另一个 MPI 二进制文件。新生成的进程将拥有自己的进程MPI_COMM_WORLD
,您无需使用MPI_Comm_split()
. 此外,spawn 操作将建立一个互通器,允许 Python 代码将消息发送到 MPI 应用程序的其他部分。
在这两种情况下,该hosts
文件都将包含可以执行 MPI 二进制文件的所有执行主机的定义。您还需要使用可用的 Python MPI 绑定之一。
请注意,您只需将一些 MPI 调用添加到您的 Python 脚本中,例如 ,MPI_Init
和相关的/ 。你不需要让它平行。MPI 用途广泛,不仅允许您将它用于并行工作共享,还可以用作通用消息传递框架。但请注意,Python 绑定应使用与程序其余部分相同的 MPI 库。MPI_Finalize
MPI_Comm_split
MPI_Send
MPI_Recv
另一种解决方案是使用一些消息队列库或文件池(这实际上是一个粗略的 MQ 实现)。