Вас может заинтересовать использование scipy.linalg.cython_lapack .
Это обеспечивает доступ к функции LAPACK dgetri
среди других. И хорошие новости это:
Это позволяет использовать BLAS и LAPACK SciPy от любого третьего лица
Модуль Cython без явного связывания с библиотеками. Это означает
что такие проекты, как scikit-learn и statsmodels, не нуждаются в поддержке
отдельная зависимость сборки от BLAS и LAPACK.
Пример использования dger
доступен на Вызов BLAS / LAPACK напрямую с использованием интерфейса SciPy и Cython . См. Также Повышение производительности Cython Lapack с помощью внутренних определений массивов?
Я подробно описал использование cython_blas в своем ответе на MPI python-Open-MPI , поэтому вот как его можно адаптировать к dgetri:
Критическая часть кода записана в Cython
, в выделенном файле myinverse.pyx
.
Этот файл превращен в myinverse.c
файл Cython
Этот файл c скомпилирован вашим любимым компилятором c gcc
для создания общей библиотеки myinverse.so
Оптимизированная функция может использоваться в вашей программе после import myinverse
.
Вот модуль Cython, который нужно поместить в файл .pyx:
import numpy
cimport numpy
cimport scipy.linalg.cython_lapack
ctypedef numpy.float64_t DTYPE_t
cimport cython
from libc.stdlib cimport malloc, free
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def invert(numpy.ndarray[DTYPE_t, ndim=2] array):
cdef int rows = array.shape[0]
cdef int cols = array.shape[1]
cdef int info = 0
if cols !=rows:
return array,1,"not a square matrix"
cdef int* ipiv = <int *> malloc(rows * sizeof(int))
if not ipiv:
raise MemoryError()
scipy.linalg.cython_lapack.dgetrf(&cols,&rows,&array[0,0],&rows,ipiv,&info)
if info !=0:
free(ipiv)
return array,info,"dgetrf failed, INFO="+str(info)
#workspace query
cdef double workl
cdef int lwork=-1
scipy.linalg.cython_lapack.dgetri(&cols,&array[0,0],&rows,ipiv,&workl,&lwork,&info)
if info !=0:
free(ipiv)
return array,info,"dgetri failed, workspace query, INFO="+str(info)
#allocation workspace
lwork= int(workl)
cdef double* work = <double *> malloc(lwork * sizeof(double))
if not work:
raise MemoryError()
scipy.linalg.cython_lapack.dgetri(&cols,&array[0,0],&rows,ipiv,work,&lwork,&info)
if info !=0:
free(ipiv)
free(work)
return array,info,"dgetri failed, INFO="+str(info)
free(ipiv)
free(work)
return array,info,""
Для цифонизации и компиляции файла .pyx можно использовать следующий make-файл (надеюсь, вы используете Linux ...)
all: myinverse myinverseb
myinverse: myinverse.pyx
cython -a myinverse.pyx
myinverseb: myinverse.c
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.7 -o myinverse.so myinverse.c
Новая функция Python myinverse, цепочка LAPACK dgetrf()
и dgetri()
, вызывается в основном файле Python:
import numpy as np
import myinverse
n=42
#A=np.zeros((n,n))
#for i in range(n):
# A[i,i]=10
A=np.random.rand(n,n)
#A=np.zeros((n,n))
Am,info,string=myinverse.invert(A.copy())
if info==0:
print np.linalg.norm(A.dot(Am)-np.identity(n), np.inf)
else :
print "inversion failed, info=",info, string