Распространение расширений на основе Cython с использованием LAPACK

Я пишу модуль Python, который включает расширения Cython и использует LAPACKBLAS). Я открыт для использования clapack или lapacke или какого-либо решения f2c или f2py, если это необходимо. Важно то, что я могу называть LAPACK и BLAS подпрограммы из Cython в узких циклах без накладных вызовов Python.

Я нашел один пример здесь. Однако этот пример зависит от SAGE. Я хочу, чтобы мой модуль устанавливался без установки SAGE, так как мои пользователи вряд ли захотят или нуждаются в SAGE для чего-либо еще. У моих пользователей, скорее всего, будут такие пакеты, как numpy, scipy, pandas и scikit learn, поэтому они будут разумными зависимостями. Какая оптимальная комбинация интерфейсов для использования, и какой бы минимальный файл setup.py выглядел так, можно было получить необходимую информацию (от numpy, scipy и т.д.) Для компиляции?

EDIT: Вот что я в итоге сделал. Он работает на моем 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)

Ответ 1

Если я правильно понял вопрос, вы можете использовать обертки SciPy Cython для процедур BLAS и LAPACK. Эти обертки описаны здесь:

Как указано в документации, вы несете ответственность за проверку того, что любые массивы, которые вы передаете этим функциям, правильно выравниваются для подпрограмм Fortran. Вы можете просто импортировать и использовать эти функции по мере необходимости в вашем .pyx файле. Например:

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

Учитывая, что это хорошо протестированный, широко используемый код, который работает на разных платформах, я бы сказал, что он является хорошим кандидатом для надежного распространения расширений Cython, которые напрямую вызывают процедуры BLAS и LAPACK.


Если вы не хотите, чтобы ваш код зависел от всего SciPy, вы можете найти много соответствующих файлов для этих функций-оболочек в каталоге SciPy linalg здесь. Полезной ссылкой является эти строки setup.py, которые перечисляют файлы источника и заголовка. Обратите внимание, что требуется компилятор Fortran!

В теории должно быть возможно изолировать только исходные файлы здесь, которые необходимы для компиляции обложек BLAS и LAPACK Cython, а затем связывать их как независимое расширение с вашим модулем.

На практике это очень сложно. Процесс сборки для субмодуля linalg требует некоторых функций Python для помощи в компиляции на разных платформах (например, из здесь). Здание также опирается на другие исходные файлы C и Fortran (здесь), пути которых жестко закодированы в эти функции Python.

Очевидно, что большая часть работы посвящена тому, чтобы SciPy правильно компилировался в разных операционных системах и архитектурах.

Я уверен, что это можно сделать, но после перетасовки файлов и перетаскивания путей я еще не нашел правильного пути для создания этой части субмодуля linalg независимо от остальной части SciPy. Если я найду правильный путь, я обязательно подтвержу этот ответ.