【问题标题】:Calling an MPI dependent Fortran module via Cython通过 Cython 调用依赖于 MPI 的 Fortran 模块
【发布时间】:2019-03-06 11:43:07
【问题描述】:

我正在尝试从 Python 调用一个使用 Open MPI 的 Fortran 库。 我选择使用 Cython 作为 Python 和 Fortran 之间的层。

我有一个从 this answer 运行的最小工作示例,但在使用 Open MPI 时遇到了问题。

您可以在下面找到我在此示例中包含 MPI 的尝试。如果我从 Fortran 程序调用模块 ffunc,它可以工作,但如果我尝试从 Python 访问它,我会得到

mca_base_component_repository_open: unable to open mca_patcher_overwrite: /path/to/mca_patcher_overwrite.so: undefined symbol: mca_patcher_base_patch_t_class (ignored)
mca_base_component_repository_open: unable to open mca_shmem_mmap: /path/to/mca_shmem_mmap.so: undefined symbol: opal_show_help (ignored)
mca_base_component_repository_open: unable to open mca_shmem_posix: /path/to/mca_shmem_posix.so: undefined symbol: opal_shmem_base_framework (ignored)
mca_base_component_repository_open: unable to open mca_shmem_sysv: /path/to/mca_shmem_sysv.so: undefined symbol: opal_show_help (ignored)

作为一个最小的工作示例,我有以下内容:

调用ffunc.p90的Fortran模块:

module ffunc

use mpi

implicit none

integer, parameter :: dp = kind(1.0d0)

contains

subroutine func(a, b, c)
  real(dp), intent(in) :: a
  real(dp), intent(in) :: b
  real(dp), intent(out) :: c
  integer :: ierr

  call mpi_init(ierr)
  c = a + b
  call mpi_finalize(ierr)

end subroutine func


end module ffunc

Fortran-C 包装器pyffunc.f90:

module fortran_wrapper


use iso_c_binding, only: c_double
use ffunc, only: func

implicit none

contains


subroutine c_func(a, b, c) bind(c)
  real(c_double), intent(in) :: a
  real(c_double), intent(in) :: b
  real(c_double), intent(out) :: c

  call func(a, b, c)

end subroutine c_func


end module fortran_wrapper

C 头 pyffunc.h:

extern void c_func(double* a, double* b, double* c);

Cython 包装器pyffunc.pyx:

cdef extern from 'pyffunc.h':
    void c_func(double* a, double* b, double* c)

def func(double a, double b):
    cdef:
        double c
    c_func(&a, &b, &c)
    print('cython: a = {}, b = {}, c = {}'.format(a, b, c))
    return c

Python setup.py(并从 mpif90 showme 获得包含和库:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
from numpy import get_include
from os import system

# compile the fortran modules without linking
fortran_mod_comp = 'mpif90 ffunc.f90 -c -o ffunc.o -O3 -fPIC'
print(fortran_mod_comp)
system(fortran_mod_comp)
shared_obj_comp = 'mpif90 pyffunc.f90 -c -o pyffunc.o -O3 -fPIC'
print(shared_obj_comp)
system(shared_obj_comp)

ext_modules = [Extension(# module name:
                         'pyffunc',
                         # source file:
                         ['pyffunc.pyx'],
                         # other compile args for gcc
                         extra_compile_args=[
                             '-fPIC',
                             '-O3',
                             '-I/usr/lib/x86_64-linux-gnu/openmpi/include',
                             '-pthread',
                             '-I/usr/lib/x86_64-linux-gnu/openmpi/lib',
                             ],
                         # other files to link to
                         extra_link_args=['ffunc.o',
                             'pyffunc.o',
                             '-pthread',
                             '-I/usr/lib/x86_64-linux-gnu/openmpi/lib',
                             '-L/usr//lib',
                             '-L/usr/lib/x86_64-linux-gnu/openmpi/lib',
                             '-lmpi_usempif08',
                             '-lmpi_usempi_ignore_tkr',
                             '-lmpi_mpifh',
                             '-lmpi',
                             ])]

setup(name = 'pyffunc',
      cmdclass = {'build_ext': build_ext},
      include_dirs = [get_include()],
ext_modules = ext_modules)

和 Python test.py 文件:

from pyffunc import func


a = 5
b = 9
c = func(5, 9)

print('python: a = {}, b = {}, c = {}'.format(a, b, c))

谁能给我一个正确方向的提示? - 我搜索了各种各样的东西,但我被困在这里。

【问题讨论】:

  • 一个选项是用configure --disable-dlopen重建Open MPI
  • @Gilles Gouaillardet 为什么以及如何帮助?
  • 长话短说:链接器的东西。我假设libmpi.so 在引擎盖下被 dlopen'ed 但没有正确的标志。你不能使用mpi 4py 吗?他们正确地解决了这个问题。
  • 哦亲爱的“链接器的东西”:-) mpi4py 看起来不错,但我不会直接使用 mpi,我只需要调用内部使用 mpi 的 fortran 例程。

标签: python fortran mpi cython openmpi


【解决方案1】:

正如@Gilles Gouaillardet 所建议的那样,诀窍确实是使用选项configure --disable-dlopen 编译Open MPI。 尽管我仍然不了解问题,也不了​​解解决方案。也许有人有更详细的答案?

【讨论】:

    猜你喜欢
    • 2021-04-21
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 2020-03-26
    • 2020-03-17
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多