1

I am trying to update the code from Fortran - Cython Workflow to use OpenMP as a toy example but I cannot install the library properly as I am getting this message:

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

I have tried everything I could find on stackoverflow, the cython doc, fortran90.org or setuptools doc but I could not make it work.
I am using Python 3.10 on Windows 11

Here's where I am:

gfunc.f90
Here I have just added the 3 omp directives

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
I have updated the compilations arguments with the -fopenmp flag and added the -openmp:llvm flag to the extra_compile_args but I'm not sure what to put in the libraries or if it is needed at all.

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
YeO
  • 938
  • 1
  • 9
  • 17

0 Answers0