通过 Cython 调用依赖 MPI 的 Fortran 模块
Calling an MPI dependent Fortran module via Cython
我正在尝试从 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)
作为一个最小的工作示例,我有以下内容:
要调用的 Fortran 模块 ffunc.p90
:
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))
谁能给我一个正确方向的提示? - 我搜索了各种东西,但我被困在这里了。
正如@Gilles Gouaillardet 所建议的那样,诀窍确实是使用选项 configure --disable-dlopen
编译 Open MPI。
虽然我仍然不明白问题所在,也不明白解决方案。也许有人有更详尽的答案?
我正在尝试从 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)
作为一个最小的工作示例,我有以下内容:
要调用的 Fortran 模块 ffunc.p90
:
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))
谁能给我一个正确方向的提示? - 我搜索了各种东西,但我被困在这里了。
正如@Gilles Gouaillardet 所建议的那样,诀窍确实是使用选项 configure --disable-dlopen
编译 Open MPI。
虽然我仍然不明白问题所在,也不明白解决方案。也许有人有更详尽的答案?