【发布时间】:2018-10-20 12:04:55
【问题描述】:
我想在 Cython 扩展中使用一些在 .c 文件中定义的使用 BLAS 子例程的 C 函数,例如
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 库,并希望它可以在使用 numpy 或 scipy 作为依赖项的不同操作系统下从 PIP 安装,而不需要任何额外的 BLAS 相关依赖项.
setup.py 是否有任何 hack 可以让我以可以与任何 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_。如果我在 .c 文件中将ddot 更改为ddot_,上面带有l:libopenblas 的代码将起作用。我仍然想知道是否有一些(理想情况下是运行时)机制来检测应该在 c 文件中使用哪个名称。
【问题讨论】:
-
scipy 已经包含了 blas-functions,你可以直接使用它docs.scipy.org/doc/scipy-0.19.0/reference/…
-
但那是为了在 Cython 中使用它们(在 .pyx 文件中)。可以以某种方式将其传递给 .c 文件中的 C 函数吗?