我希望在Cython扩展中使用一些在.c文件中定义的C函数,这些函数使用BLAS子例程,例如:
cfile.c
double ddot(int *N, double *DX, int *INCX, double *DY, int *INCY);
double call_ddot(double* a, double* b, int n){
int one = 1;
return ddot(&n, a, &one, b, &one);
}
假设这些函数不仅仅调用一个BLAS子程序
pyfile.pyx
cimport numpy as np
import numpy as np
cdef extern from "cfile.c":
double call_ddot(double* a, double* b, int n)
def pyfun(np.ndarray[double, ndim=1] a):
return call_ddot(&a[0], &a[0], <int> a.shape[0])
setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext
import numpy
setup(
name = "wrapped_cfun",
packages = ["wrapped_cfun"],
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("wrapped_cfun.cython_part", sources=["pyfile.pyx"], include_dirs=[numpy.get_include()])]
)
我希望这个软件包能够链接到已安装的NumPy或SciPy使用的相同BLAS库,并且希望它可以作为PIP的依赖项,在不同操作系统下使用numpy或scipy进行安装,而无需任何额外的BLAS相关依赖关系。
是否有任何hack方法可以在setup.py中实现这一点,以使其能够与任何BLAS实现一起工作?
更新: 使用MKL,我可以通过修改Extension对象来让它指向libmkl_rt来使它工作,如果安装了MKL,则可以从numpy中提取它,例如: Extension("wrapped_cfun.cython_part", sources=["pyfile.pyx"], include_dirs=[numpy.get_include()], extra_link_args=["-L{path to python's lib dir}", "-l:libmkl_rt.{so, dll, dylib}"]) 然而,对于OpenBLAS(例如-l:libopenblasp-r0.2.20.so),同样的技巧不起作用。如果该文件是链接到libopenblas,那么指向libblas.{so,dll,dylib}将不起作用,但如果链接到libmkl_rt则正常工作。
更新2: 似乎OpenBLAS将他们的C函数命名为末尾带有下划线的符号,例如不是ddot而是ddot_。上面的代码与l:libopenblas一起使用将起作用,如果我在.c文件中将ddot更改为ddot_。 我仍在想是否有某种(理想情况下是运行时)机制来检测应在c文件中使用哪个名称。