在 C 語言中嵌入 mpi4py 程序

本文從本人簡書博客同步過來

上一篇中我們介紹了用 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 文檔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章