美文网首页Python 并行计算
在 C 语言中嵌入 mpi4py 程序

在 C 语言中嵌入 mpi4py 程序

作者: 自可乐 | 来源:发表于2018-05-22 21:35 被阅读119次

    上一篇中我们介绍了用 f2py 包装 Fortran 语言 MPI 程序以供 mpi4py 调用的方法,可以看到包装 C, C++,Fortran 等其它计算机语言的 MPI 程序供 mpi4py 调用是比较容易的,其实反过来将 mpi4py 程序嵌入其它计算机语言中也不难,下面我们将介绍在 C 语言程序中嵌入 mpi4py 程序的方法。

    Python 与 C 之间的互操作在底层都是通过 Python/C API 实现的,要在 C 语言中嵌入 mpi4py 程序也是通过 Python/C API 的相关函数实现的。最简单的方法是使用函数 PyRun_SimpleString 直接执行一段 mpi4py 程序代码,不过需要注意的是要首先包含 mpi.h 和 Python.h 头文件,并初始化 MPI 和 Python 环境,等执行完 Python 程序后,记得要释放 MPI 和 Python 环境。举例如下:

    /* helloworld.c */
    
    #include <mpi.h>
    #include <Python.h>
    
    const char helloworld[] = \
      "from mpi4py import MPI                                \n"
      "hwmess = 'Hello, World! I am process %d of %d on %s.' \n"
      "myrank = MPI.COMM_WORLD.Get_rank()                    \n"
      "nprocs = MPI.COMM_WORLD.Get_size()                    \n"
      "procnm = MPI.Get_processor_name()                     \n"
      "print (hwmess % (myrank, nprocs, procnm))             \n"
      "";
    
    int main(int argc, char *argv[])
    {
      MPI_Init(&argc, &argv);
      Py_Initialize();
    
      PyRun_SimpleString(helloworld);
    
      MPI_Finalize(); /* MPI should be finalized */
      Py_Finalize();  /* after finalizing Python */
    
      return 0;
    }
    

    可以使用类似下面的命令编译和生成可执行程序 helloworld (注意将其中的路径改成你的系统中实际的路径):

    $ mpicc -I/path/to/python/include/python2.7 -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -o helloworld helloworld.c -L/path/to/python/lib/python2.7/config -lpthread -ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic
    

    执行结果如下:

    $ mpiexec -n 4 ./helloworld
    Hello, World! I am process 1 of 4 on node2.
    Hello, World! I am process 3 of 4 on node2.
    Hello, World! I am process 2 of 4 on node2.
    Hello, World! I am process 0 of 4 on node2.
    

    也可以将要嵌入的 mpi4py 程序放入单独的文件,如 helloworld.py,然后使用 PyRun_SimpleFile 函数来执行它,如下:

    # helloworld.py
    
    from mpi4py import MPI
    
    
    hwmess = 'Hello, World! I am process %d of %d on %s.'
    myrank = MPI.COMM_WORLD.Get_rank()
    nprocs = MPI.COMM_WORLD.Get_size()
    procnm = MPI.Get_processor_name()
    print (hwmess % (myrank, nprocs, procnm))
    
    /* helloworld.c */
    
    #include <mpi.h>
    #include <Python.h>
    
    int main(int argc, char *argv[])
    {
      const char *fname = "./helloworld.py";
      FILE *fp;
    
      MPI_Init(&argc, &argv);
      Py_Initialize();
    
      fp = fopen(fname, "r");
      PyRun_SimpleFile(fp, fname);
    
      MPI_Finalize(); /* MPI should be finalized */
      Py_Finalize();  /* after finalizing Python */
    
      return 0;
    }
    

    为了方便,我们也可以编写如下 Makefile 以简化编译操作(注意其中使用了在上一篇中介绍的 python-config 文件):

    # Makefile
    
    .PHONY: default build test clean
    
    default: build test clean
    
    PYTHON = python
    PYTHON_CONFIG = ${PYTHON} ./python-config
    
    MPICC   = mpicc
    CFLAGS  = ${shell ${PYTHON_CONFIG} --cflags}
    LDFLAGS = ${shell ${PYTHON_CONFIG} --ldflags}
    build: helloworld
    helloworld: helloworld.c
        ${MPICC} ${CFLAGS} -o $@ $< ${LDFLAGS}
    
    
    MPIEXEC = mpiexec
    NP_FLAG = -n
    NP = 5
    test: build
        ${MPIEXEC} ${NP_FLAG} ${NP} ./helloworld
    
    
    clean:
        ${RM} -r helloworld
    

    编译扩展库,执行程序及清理可以分别使用如下命令:

    $ make build
    $ make test
    $ make clean
    

    以上非常简单地介绍了在 C 语言中嵌入 mpi4py 程序的方法,更多的内容可以参考 Python/C API 文档。

    前面我们所给出的各个例程一般都是在单台计算机上直接使用 mpiexec 或 mpirun 执行的,但是在实际应用中,对规模比较大的高性能计算任务,一般会提交到集群或超级计算机平台上进行计算。集群系统具有低成本、高性能的特性,提供了强大的批处理和并行计算能力,代表了高性能计算机发展的新方向。在集群或者超级计算机平台上,一般不能随意地直接以 mpiexec 或 mpirun 运行我们的并行计算程序,而必须通过其上提供的作业管理系统来提交计算任务。作为集群系统软件的重要组成部分,集群作业管理系统可以根据用户的需求,统一管理和调度集群的软硬件资源,保证用户作业公平合理地共享集群资源,提高系统利用率和吞吐率。下面我们将简要地介绍几个常用的集群作业管理系统:PBS,LSF 和 SLURM。在下一篇中我们首先简要介绍 PBS 作业管理系统。

    相关文章

      网友评论

        本文标题:在 C 语言中嵌入 mpi4py 程序

        本文链接:https://www.haomeiwen.com/subject/vgnkjftx.html