【问题标题】:How to pass an MPI communicator from python to C via cython?如何通过 cython 将 MPI 通信器从 python 传递到 C?
【发布时间】:2019-01-04 12:43:16
【问题描述】:

我正在尝试通过 cython 包装一个将 MPI_Comm 通信器句柄作为参数的 C 函数。因此,我希望能够从 python 调用该函数,并将其传递给 mpi4py.MPI.Comm 对象。我想知道的是,如何将mpi4py.MPI.Comm 转换为MPI_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 应该给出类似的东西:

你好,世界!我是 4 个进程中的第 0 个进程。
你好世界!我是 4 个过程中的第 1 个。
你好世界!我是第 2 个过程,共 4 个。
你好世界!我是 4 个过程中的第 3 个。

但如果我尝试像这样通过 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
)

我收到以下错误消息:

helloworld_wrap.pyx:8:13:无法将 Python 对象转换为“MPI_Comm”

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

【问题讨论】:

    标签: python c mpi cython mpi4py


    【解决方案1】:

    转换相当简单,因为mpi4py.MPI.Comm-object 在内部将MPI_Comm 句柄存储为成员ob_mpi1。因此,如果将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

    【讨论】:

    • 根据我的经验,mpi4py 的文档记录严重不足,并且经常需要查看源代码以弄清楚事情是如何工作的。
    • @Zulan 我也有这种感觉。我想,我至少会在这里记录一下。
    猜你喜欢
    • 2017-07-20
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 2014-03-10
    • 2022-01-22
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多