如何通过cython将MPI通信器从python传递到C? [英] How to pass an MPI communicator from python to C via cython?
问题描述
我正在尝试通过cython封装一个以MPI_Comm
通信器句柄为参数的C函数.结果,我希望能够从python调用该函数,并将其传递给mpi4py.MPI.Comm
对象.我想知道的是,如何进行从mpi4py.MPI.Comm
到MPI_Comm
的转换.
I am trying to wrap a C function taking an MPI_Comm
communicator handle as a parameter via cython. As a result, I want to be able to call the function from python, passing it an mpi4py.MPI.Comm
object. What I am wondering is, how to make the conversion from mpi4py.MPI.Comm
to MPI_Comm
.
为了演示,我使用一个简单的"Hello World!"类型的函数:
To demonstrate, I use a simple "Hello World!"-type function:
helloworld.h
:
#ifndef HELLOWORLD
#define HELLOWORLD
#include <mpi.h>
void sayhello(MPI_Comm comm);
#endif
helloworld.c
:
#include <stdio.h>
#include "helloworld.h"
void sayhello(MPI_Comm comm){
int size, rank;
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
printf("Hello, World! "
"I am process %d of %d.\n",
rank, size);
}
我现在想像这样从python调用此函数:
I now want to call this function from python like this:
from_python.py
:
import mpi4py
import helloworld_wrap
helloworld_wrap.py_sayhello(mpi4py.MPI.COMM_WORLD)
表示mpirun -np 4 python2 from_python.py
应该给出类似的内容:
Meaning that mpirun -np 4 python2 from_python.py
is supposed to give something like:
你好,世界!我正在处理0之4.
你好,世界!我是第1步,共4步.
你好,世界!我正在执行第2步,共4步.
你好,世界!我正在处理3之4.
Hello, World! I am process 0 of 4.
Hello, World! I am process 1 of 4.
Hello, World! I am process 2 of 4.
Hello, World! I am process 3 of 4.
但是,如果我尝试通过cython来实现这一目标,
But if I try to achieve this via cython like this:
helloworld_wrap.pyx
:
cimport mpi4py.MPI as MPI
cimport mpi4py.libmpi as libmpi
cdef extern from "helloworld.h":
void sayhello(libmpi.MPI_Comm comm)
def py_sayhello(MPI.Comm comm):
sayhello(comm)
和:
setup.py
:
import os
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
mpi_compile_args = os.popen("mpicc --showme:compile").read().strip().split(' ')
mpi_link_args = os.popen("mpicc --showme:link").read().strip().split(' ')
ext_modules=[
Extension("helloworld_wrap",
sources = ["helloworld_wrap.pyx", "helloworld.c"],
language = 'c',
extra_compile_args = mpi_compile_args,
extra_link_args = mpi_link_args,
)
]
setup(
name = "helloworld_wrap",
cmdclass = {"build_ext": build_ext},
ext_modules = ext_modules
)
我收到以下错误消息:
helloworld_wrap.pyx:8:13:无法将Python对象转换为"MPI_Comm"
helloworld_wrap.pyx:8:13: Cannot convert Python object to 'MPI_Comm'
表示不能将mpi4py.MPI.Comm
转换为MPI_Comm
.那么如何将mpi4py.MPI.Comm
转换为MPI_Comm
以便使包装器正常工作?
indicating that mpi4py.MPI.Comm
can't be converted into an MPI_Comm
. So how can I convert the mpi4py.MPI.Comm
into an MPI_Comm
in order to get my wrapper to work?
推荐答案
转换非常简单,因为mpi4py.MPI.Comm
对象内部将MPI_Comm
句柄存储为成员ob_mpi
1 .因此,如果将helloworld_wrap.pyx
的最后一行更改为通过comm.ob_mpi
而不是comm
,则模块将按预期进行编译和工作:
The conversion is rather simple, as a mpi4py.MPI.Comm
-object internally stores an MPI_Comm
handle as member ob_mpi
1. Therefore, if one changes the last line of helloworld_wrap.pyx
to pass comm.ob_mpi
instead of comm
, the module compiles and works as intended:
helloworld_wrap.pyx
:
cimport mpi4py.MPI as MPI
cimport mpi4py.libmpi as libmpi
cdef extern from "helloworld.h":
void sayhello(libmpi.MPI_Comm comm)
def py_sayhello(MPI.Comm comm):
sayhello(comm.ob_mpi)
Surprisingly, I did not find any documentation for this but only realized this when studying the sources of mpi4py.MPI.Comm
. I am not sure, if this is the intended way to handle this, but I could not get it to work otherwise.
1 实际上,如果mpi4py.MPI
中的大多数对象(如果不是在C中为相应的MPI句柄建模的所有对象),都将相应的句柄作为成员ob_mpi
持有.
1 In fact, most, if not all objects in mpi4py.MPI
that model a corresponding MPI handle in C, hold a corresponding handle as member ob_mpi
.
这篇关于如何通过cython将MPI通信器从python传递到C?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!