Windows下用OpenMP编译链接Fortran+Cython扩展时遇链接错误
我正尝试将Fortran-Cython工作流的代码更新为支持OpenMP的示例,但安装库时链接失败,出现以下错误:
gfunc.o : error LNK2001: unresolved external symbol ___chkstk_ms
gfunc.o : error LNK2001: unresolved external symbol GOMP_atomic_start
gfunc.o : error LNK2001: unresolved external symbol GOMP_atomic_end
gfunc.o : error LNK2001: unresolved external symbol GOMP_parallel
build\lib.win-amd64-cpython-310\pygfunc\pygfunc.cp310-win_amd64.pyd : fatal error LNK1120: 4 unresolved externals
error: command 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.34.31933\bin\HostX86\x64\link.exe' failed with exit code 1120
我已查阅Stack Overflow、Cython文档、fortran90.org及setuptools文档,但问题仍未解决。使用环境为Windows 11 + Python 3.10。
相关文件
gfunc.f90(已添加OpenMP指令)
module gfunc_module !$ use omp_lib implicit none contains subroutine gfunc(x, n, m, a, b, c) double precision, intent(in) :: x integer, intent(in) :: n, m double precision, dimension(n), intent(in) :: a double precision, dimension(m), intent(in) :: b double precision, dimension(n, m), intent(out) :: c integer :: i, j !$OMP PARALLEL DO do j=1,m do i=1,n c(i,j) = exp(-x * (a(i)**2 + b(j)**2)) end do end do !$OMP END PARALLEL DO end subroutine end module
gfunc_wrapper.f90
module gfunc_interface use iso_c_binding, only: c_double, c_int use gfunc_module, only: gfunc implicit none contains subroutine c_gfunc(x, n, m, a, b, c) bind(c) real(c_double), intent(in) :: x integer(c_int), intent(in) :: n, m real(c_double), dimension(n), intent(in) :: a real(c_double), dimension(m), intent(in) :: b real(c_double), dimension(n, m), intent(out) :: c call gfunc(x, n, m, a, b, c) end subroutine end module
gfunc.h
extern void c_gfunc(double* x, int* n, int* m, double* a, double* b, double* c);
pygfunc.pyx
#cython: language_level=3 from numpy import linspace, empty from numpy cimport ndarray as ar cdef extern from "gfunc.h": void c_gfunc(double* a, int* n, int* m, double* a, double* b, double* c) def f(double x, double a=-10.0, double b=10.0, int n=100): cdef: ar[double] ax = linspace(a, b, n) ar[double,ndim=2] c = empty((n, n), order='F') c_gfunc(&x, &n, &n, <double*> ax.data, <double*> ax.data, <double*> c.data) return c
setup.py(已尝试添加-fopenmp和-openmp:llvm参数,不确定libraries设置)
from os import system from numpy import get_include from setuptools import Extension, setup from Cython.Distutils import build_ext # compile the fortran modules without linking # fortran_mod_comp = 'gfortran pygfunc/gfunc.f90 -c -o gfunc.o -O3 -fPIC' fortran_mod_comp = 'gfortran -fopenmp pygfunc/gfunc.f90 -c -o gfunc.o -O3 -fPIC' print(fortran_mod_comp) system(fortran_mod_comp) # shared_obj_comp = 'gfortran pygfunc/gfunc_wrapper.f90 -c -o gfunc_w.o -O3 -fPIC' shared_obj_comp = 'gfortran -fopenmp pygfunc/gfunc_wrapper.f90 -c -o gfunc_w.o -O3 -fPIC' print(shared_obj_comp) system(shared_obj_comp) setup( cmdclass={'build_ext': build_ext}, ext_modules = [ Extension( name='pygfunc.pygfunc', sources=['pygfunc/pygfunc.pyx'], include_dirs=[get_include()], libraries=['libomp'], extra_compile_args=['-openmp:llvm'], extra_link_args=['gfunc.o', 'gfunc_w.o'] ) ] )
setup.cfg
[metadata] name = pygfunc version = attr: pygfunc.__version__ [options] zip_safe = False packages = find: install_requires = numpy python_requires = >=3.7
内容的提问来源于stack exchange,提问作者YeO

