使用LAPACK分发基于Cython的扩展


67

我正在编写一个包含Cython扩展和用法LAPACK(和BLAS)的Python模块。我打开使用两种clapacklapacke,或某种f2cf2py解决方案,如果必要的。重要的是,我能够在紧密的循环中从Cython调用lapackblas例程,而没有Python调用开销。

我在这里找到了一个例子。但是,该示例取决于SAGE。我希望我的模块无需安装SAGE就可以安装,因为我的用户不太可能需要SAGE或其他任何东西。我的用户可能安装了numpy,scipy,pandas和scikit Learn之类的程序包,因此这些程序包是合理的依赖项。使用的接口的最佳组合是什么?最小的setup.py文件看起来像什么,可以从中获取编译所需的信息(从numpy,scipy等)?

编辑: 这就是我最终在做什么。它可以在我的Macbook上使用,但我不知道它的便携性。当然有更好的方法。

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy
from Cython.Build import cythonize
from numpy.distutils.system_info import get_info

# TODO: This cannot be the right way
blas_include = get_info('blas_opt')['extra_compile_args'][1][2:]
includes = [blas_include,numpy.get_include()]

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = cythonize([Extension("cylapack", ["cylapack.pyx"],
                                       include_dirs = includes,
                                       libraries=['blas','lapack'])
                   ])
)

之所以可行,是因为在我的Macbook上,clapack.h头文件与处于同一目录中cblas.h。然后,我可以在pyx文件中执行此操作:

ctypedef np.int32_t integer

cdef extern from "cblas.h":
    double cblas_dnrm2(int N,double *X, int incX)
cdef extern from "clapack.h":
    integer dgelsy_(integer *m, integer *n, integer *nrhs, 
    double *a, integer *lda, double *b, integer *ldb, integer *
    jpvt, double *rcond, integer *rank, double *work, integer *
    lwork, integer *info)

Answers:


5

如果我对问题的理解正确,则可以将SciPy的Cython包装器用于BLAS和LAPACK例程。这些包装器记录在这里:

如文档所述,您有责任检查传递给这些函数的所有数组是否与Fortran例程正确对齐。您可以根据需要在.pyx文件中简单地导入和使用这些功能。例如:

from scipy.linalg.cython_blas cimport dnrm2 
from scipy.linalg.cython_lapack cimport dgelsy 

鉴于这是在不同平台上运行的经过良好测试的,广泛使用的代码,我认为它是可靠分发直接调用BLAS和LAPACK例程的Cython扩展的理想选择。


如果您不希望代码依赖于整个SciPy,则可以在SciPy的linalg目录中找到这些包装函数的许多相关文件。有用的参考是setup.py的这些行,其中列出了源文件和头文件。请注意,需要Fortran编译器!

理论上讲,应该只在这里隔离编译BLAS和LAPACK Cython包装器所需的源文件,然后将它们捆绑为模块的独立扩展即可。

实践中,这很奇怪。linalg子模块的构建过程需要一些Python函数来帮助在不同平台上进行编译(例如从here)。构建还依赖于其他C和Fortran源文件(在此),这些文件的路径被硬编码到这些Python函数中。

显然,要确保SciPy在不同的操作系统和体系结构上正确编译,已经进行了很多工作。

我敢肯定这是可行的,但是在整理文件并调整路径之后,我还没有找到独立于SciPy其余部分来构建linalg子模块这一部分的正确方法。如果我找到正确的方法,我将确保更新此答案。


1
我的印象是,问题更多是关于如何链接到scipy / numpy附带的blas,并使其在多台计算机(安装了scipy / numpy)上工作而不必在每台计算机上重新编译。但是使用提供的scipy包装器的建议是好的。
DavidW

嗯,你可能是正确的。如果OP提供了进一步的说明,我可以根据需要改进或删除此答案(或将其转换为评论)。
亚历克斯·莱利

这是一种很好的方法。@DavidW是正确的,因为我一直在寻找一种便携式的解决方案,并且不需要用户安装其他库。我认为这是带有适当的setup.py文件的那些事情。ajcr,您能否添加示例setup.py来显示如何获取任何必要的包含目录等?我认为numpy.get_include()就是需要的吗?
jcrudy

@jcrudy那时我可能会有点误解:您正在寻找的是可移植的东西(我认为这个答案很适合),而不是让您随身移动已编译的库的东西(我不确定是否可能去工作)?如果真是这样,我想这个答案
可以满足

2
对于以后阅读这些内容的人来说setup.py,使用SciPy的包装程序无需对文件进行任何特殊处理。
IanH
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.