在上一篇中我们介绍了使用 scalapy 调用 ScaLAPACK 进行分布式内存的线性代数运算。Python 作为一种胶水语言,可以非常容易地包装和调用其它计算机语言已有的程序代码和工具库,如果我们有用 C,C++,Fortran 或其它计算机语言编写的 MPI 计算程序,也能很容易地将其包装后在 mpi4py 中进行调用。另外我们也可以用这些计算机语言编写一些运算速度更快的 MPI 扩展模块供 mpi4py 程序调用。在下面的章节中我们将介绍怎么在 mpi4py 程序中包装和调用 C,C++,Fortran 的 MPI 程序。下面我们首先介绍直接使用 Python/C API 进行 C 语言 MPI 程序包装的方法。
Python 文档中有使用 C/C++ 写扩展模块的详细文档和完整的 Python/C API 参考,此处不会专门讲解怎么使用 Python/C API 编写扩展模块,只会介绍如何在 mpi4py 程序中包装和调用已经存在的 C 语言 MPI 程序代码。
假设我们有如下使用 Python/C API 编写的扩展 C 语言 MPI 程序,其中定义了 sayhello 函数,这个函数接受一个 MPI 通信子作为参数,在其中调用 MPI 的相关函数完成计算工作:
/* helloworld.c */
#define MPICH_SKIP_MPICXX 1
#define OMPI_SKIP_MPICXX 1
#include <mpi4py/mpi4py.h>
/* -------------------------------------------------------------------------- */
static void
sayhello(MPI_Comm comm) {
int size, rank;
char pname[MPI_MAX_PROCESSOR_NAME]; int len;
if (comm == MPI_COMM_NULL) {
printf("You passed MPI_COMM_NULL !!!\n");
return;
}
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
MPI_Get_processor_name(pname, &len);
pname[len] = 0;
printf("Hello, World! I am process %d of %d on %s.\n",
rank, size, pname);
}
/* -------------------------------------------------------------------------- */
static PyObject *
hw_sayhello(PyObject *self, PyObject *args)
{
PyObject *py_comm = NULL;
MPI_Comm *comm_p = NULL;
if (!PyArg_ParseTuple(args, "O:sayhello", &py_comm))
return NULL;
comm_p = PyMPIComm_Get(py_comm);
if (comm_p == NULL)
return NULL;
sayhello(*comm_p);
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef hw_methods[] = {
{
"sayhello", (PyCFunction)hw_sayhello, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL} /* sentinel */