通过(非MPI)python脚本与MPI二进制文件交互

thi*_*sch 3 python interaction mpi

我想通过例如(串行)python脚本以某种方式触发MPI程序的某些功能(用C++编写)的执行.这个python脚本应该在开始时启动mpi程序,例如,

subprocess.call(['mpirun','-np', '4', 'mpibinary', 'args' ])
Run Code Online (Sandbox Code Playgroud)

我需要多次调用这个MPI程序的函数,我想避免为不同的输入重新启动程序,因为我必须重新初始化我的所有数据结构,这是昂贵的.因此,我想到了当MPI程序空闲时外部触发一个功能.我认为这可以通过文件IO完成,即MPI程序的根级别在while(1)循环中监视某个文件,并且一旦其内容改变,它就会解析新内容,通知其他级别并调用函数.我的问题有更优雅的解决方案吗?

最好的解决方案是拥有一个python类,它包装了C++ MPI程序的重要功能,以便我可以从python中调用它们

mpiprogram.superfunction(a,b)
Run Code Online (Sandbox Code Playgroud)

Hri*_*iev 5

也许最优雅的解决方案是将Python代码作为MPI应用程序的一部分.然后,它将能够直接将数据(通过MPI消息)发送到MPI应用程序的其余部分,因为它将成为其中的一部分.这里有两种不同的方法:

1)在您的MPI作业中将Python二进制文件作为等级0插入.为了将其排除在参与集体行动之外mpibinary,你必须建立一个不包括0级的子通信员,并将其用于所有进一步的集体通信mpibinary.第一步是简单的部分.在Open MPI中你会这样做:

mpirun --hostfile hosts -np 1 pythonbinary args : -np 32 mpibinary args
Run Code Online (Sandbox Code Playgroud)

这称为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)
Run Code Online (Sandbox Code Playgroud)

在C++中:

int rank;
MPI_Comm c_comm;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_split(MPI_COMM_WORLD, 1, rank, &c_comm);
Run Code Online (Sandbox Code Playgroud)

通过使用rankas键,可以保证进程的顺序c_comm与分割前的顺序相同,即等级1 MPI_COMM_WORLD将变为等级0 c_comm,等级2将变为等级1,等等.

从现在开始,C++应用程序可以c_comm像往常一样用于执行集合操作.为了在Python和C++代码之间进行通信,您仍然必须使用MPI_COMM_WORLD,并且Python代码仍然在其中排名为0.

2)使用MPI-2过程管理设施.首先,您将运行仅包含Python二进制文件的MPI作业:

mpirun --hostfile hosts -np 1 pythonbinary args
Run Code Online (Sandbox Code Playgroud)

然后,Python二进制文件将使用MPI_Comm_spawn()所需数量的新进程直接生成其他MPI二进制文件.新生成的进程将拥有自己的进程MPI_COMM_WORLD,您不需要使用MPI_Comm_split().此外,spawn操作将建立一个intercommunicator,允许Python代码将消息发送到MPI应用程序的其他部分.


在这两种情况下,该hosts文件都将包含可以执行MPI二进制文件的所有执行主机的定义.您还需要使用一个可用的Python MPI绑定.

请注意,您只需要添加一些MPI调用你的Python脚本一样MPI_Init,MPI_Finalize,MPI_Comm_split和相关的MPI_Send/ MPI_Recv.你不需要使它平行.MPI非常通用,它不仅可以用于并行工作共享,还可以用作通用消息传递框架.但请注意,Python绑定应使用与程序其余部分相同的MPI库.

另一种解决方案是使用一些消息队列库或文件池(这实际上是一个粗略的MQ实现).