如何将Python与使用MPI的C程序进行交互

问题描述 投票:1回答:2

目前我有一个Python程序(串行)通过subprocess.run调用C可执行文件(通过MPI并行)。但是,这是一个非常笨重的实现,因为它意味着我必须使用文件系统将一些非常大的数组从Python传递到C程序。我希望能够直接将数组从Python传递给C并返回。我认为ctypes是我应该使用的。据我了解,我将创建一个DLL而不是我的C代码中的可执行文件,以便能够与Python一起使用它。

但是,要使用MPI,您需要使用mpirun / mpiexec启动程序。如果我只是使用dll中的C函数,这是不可能的,对吗?

有没有一种好方法为从dll调用的函数启用MPI?我发现的两种可能性是

  • 使用mpi4py并行启动python程序,然后将MPI_COMM_WORLD传递给C函数(根据此帖子How to pass MPI information to ctypes in python
  • 以某种方式初始化和生成函数内的进程,而不使用mpirun。我不确定这是否可行。
mpi
2个回答
0
投票

一种可能性,如果你可以通过c程序等级0传递所有内容,那就是使用subprocess.Popen()stdin=subprocess.PIPE以及python方面的communicate()函数和c方面的fread()

这显然是脆弱的,但确实将一切都记在了内存中。此外,如果您的数据大小(您说它是),您可能必须将数据写入子进程中的子进程。另一种选择可能是使用exe.stdin.write(x)而不是exe.communicate(x)

我创建了一个小例子程序

c代码(程序名为child):

#include "mpi.h"
#include "stdio.h"

int main(int argc, char *argv[]){
    MPI_Init(&argc, &argv);

    int size, rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    double ans;
    if(rank == 0){
        fread(&ans, sizeof(ans), 1, stdin);
    }

    MPI_Bcast(&ans, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    printf("rank %d of %d received %lf\n", rank, size, ans);
    MPI_Finalize();
}

python代码(名为driver.py):

#!/usr/bin/env python

import ctypes as ct
import subprocess as sp

x = ct.c_double(3.141592)

exe = sp.Popen(['mpirun', '-n', '4', './child'], stdin=sp.PIPE)
exe.communicate(x)

x = ct.c_double(101.1)

exe = sp.Popen(['mpirun', '-n', '4', './child'], stdin=sp.PIPE)
exe.communicate(x)

结果:

> python ./driver.py
rank 0 of 4 received 3.141592
rank 1 of 4 received 3.141592
rank 2 of 4 received 3.141592
rank 3 of 4 received 3.141592
rank 0 of 4 received 101.100000
rank 2 of 4 received 101.100000
rank 3 of 4 received 101.100000
rank 1 of 4 received 101.100000

我尝试通过mpi4py使用MPI_Comm_connect()MPI_Comm_accept(),但我似乎无法在python端工作。


0
投票

由于大部分时间都花在多次调用的C子例程上,并且您在资源管理器中运行,我建议采用以下方法:

通过以下命令立即启动所有MPI任务(假设您已分配n+1插槽

mpirun -np 1 python wrapper.py : -np <n> a.out

您可能希望从MPI_Comm_split()开始,以便仅为n程序实现的C任务生成通信器。然后你将定义一个“协议”,以便python包装器可以将参数传递给C任务,并等待结果或将C程序指向MPI_Finalize()

你不妨考虑使用一个内部通信器(第一组用于python,第二组用于C),但这完全取决于你。 Intercommunicator语义可以被视为非直观的,因此如果您想要进入该方向,请确保您了解其工作原理。

© www.soinside.com 2019 - 2024. All rights reserved.