【问题标题】:Distributing Cython based extensions using LAPACK使用 LAPACK 分发基于 Cython 的扩展
【发布时间】:2013-01-29 16:02:52
【问题描述】:

我正在编写一个包含 Cython 扩展并使用 LAPACK(和 BLAS)的 Python 模块。如有必要,我愿意使用clapacklapacke,或某种f2cf2py 解决方案。重要的是我能够在没有 Python 调用开销的情况下从 Cython 调用 lapackblas 例程。

我找到了一个例子here。但是,该示例取决于 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)

【问题讨论】:

    标签: python numpy cython lapack blas


    【解决方案1】:

    如果我正确理解了这个问题,您可以将 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 目录 here 中找到这些包装函数的许多相关文件。一个有用的参考是these lines of setup.py,它列出了源文件和头文件。请注意,需要 Fortran 编译器!

    theory 中,应该可以仅在此处隔离编译 BLAS 和 LAPACK Cython 包装器所需的源文件,然后将它们作为独立扩展与您的模块捆绑在一起。

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

    显然,为了确保 SciPy 在不同的操作系统和架构上正确编译,我们做了很多工作。

    我确定可以这样做,但是在对文件进行混洗和调整路径之后,我还没有找到正确的方法来独立于 SciPy 的其余部分构建 linalg 子模块的这一部分。如果我找到正确的方法,我一定会更新这个答案。

    【讨论】:

    • 我的印象是,问题更多是关于如何链接到 scipy/numpy 附带的 blas 并让它在多台计算机上工作(安装了 scipy/numpy),而无需在每台计算机上重新编译.但是使用 scipy 提供的包装器的建议很好。
    • 啊,你可能是对的。如果 OP 提供进一步说明,我可以根据需要改进或删除此答案(或将其转换为评论)。
    • 这是一个很好的方法。 @DavidW 是正确的,我正在寻找一种可移植且不需要用户安装其他库的解决方案。我认为这是具有适当 setup.py 文件的那些东西。 ajcr,您能否添加一个示例 setup.py 显示如何获取任何必要的包含目录等?我认为 numpy.get_include() 就足够了吗?
    • @jcrudy 那时我可能有点误解了:您正在寻找可移植编译的东西(我认为这个答案有好处),而不是让您移动编译的库的东西便携(我不确定它是否可能起作用)?如果是这种情况,那么我认为这个答案可以满足您的大部分需求(可能 setup.py 除外)
    • 对于那些稍后阅读本文的人,无需在 setup.py 文件中执行任何特殊操作即可使用来自 SciPy 的包装器。
    猜你喜欢
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2012-06-10
    相关资源
    最近更新 更多