我正在尝试通过 cython 包装一个将 MPI_Comm 通信器句柄作为参数的 C 函数。因此,我希望能够从 python 调用该函数,并将其传递给 mpi4py.MPI.Comm 对象。我想知道的是,如何进行从 mpi4py.MPI.CommMPI_Comm 的转换。

为了演示,我使用了一个简单的“Hello World!”类型的函数:
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 调用这个函数:
from_python.py :

import mpi4py
import helloworld_wrap

helloworld_wrap.py_sayhello(mpi4py.MPI.COMM_WORLD)

这意味着 mpirun -np 4 python2 from_python.py 应该给出如下内容:



但是,如果我尝试通过这样的 cython 实现这一点:
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
)

我收到以下错误消息:



表示 mpi4py.MPI.Comm 不能转换为 MPI_Comm 。那么如何将 mpi4py.MPI.Comm 转换为 MPI_Comm 以使我的包装器工作?

最佳答案

转换相当简单,因为 mpi4py.MPI.Comm 对象在内部将 MPI_Comm 句柄存储为成员 ob_mpi 1。因此,如果更改 helloworld_wrap.pyx 的最后一行以传递 comm.ob_mpi 而不是 comm ,该模块将按预期编译和工作:
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)

令人惊讶的是,我没有找到任何相关文档,但只有在研究 sources of mpi4py.MPI.Comm 时才意识到这一点。我不确定,这是否是处理此问题的预期方式,但否则我无法使其正常工作。

1 事实上,mpi4py.MPI 中的大多数对象(如果不是全部)在 C 中对相应的 MPI 句柄进行建模,都将相应的句柄作为成员 ob_mpi 持有。

关于python - 如何通过cython将MPI通信器从python传递到C?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51557135/

10-12 15:39