2013-02-13 16 views
64

Piszę moduł Pythona, który zawiera rozszerzenia Cython i używa LAPACK (i BLAS). Jestem otwarty na używanie albo clapack lub lapacke, albo pewnego rodzaju rozwiązania f2c lub f2py, jeśli to konieczne. Ważne jest to, że mogę wywoływać procedury z Cythona w ciasnych pętlach bez obciążania wywołaniem Pythona.Dystrybucja rozszerzeń opartych na języku Cython przy użyciu LAPACK

Znalazłem jeden przykład: here. Jednak ten przykład zależy od SAGE. Chcę, aby mój moduł był instalowalny bez instalowania SAGE, ponieważ moi użytkownicy prawdopodobnie nie będą chcieli lub potrzebują SAGE do niczego innego. Moi użytkownicy prawdopodobnie będą mieć zainstalowane pakiety takie jak numpy, scipy, pandy i scikit Learn, więc będą to uzasadnione zależności. Jaka jest najlepsza kombinacja interfejsów i jak wyglądałby minimalny plik setup.py, który mógłby pobrać potrzebne informacje (z numpy, scipy itp.) Do kompilacji?

EDYCJA: Oto, co zrobiłem. Działa na moim macbooku, ale nie mam pojęcia, jak to jest przenośne. Na pewno jest lepszy sposób.

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']) 
        ]) 
) 

To działa, ponieważ na moim macbook, plik clapack.h nagłówek jest w tym samym katalogu co cblas.h. Mogę wtedy zrobić to w moim pliku 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) 

Odpowiedz

4

Jeśli dobrze zrozumiałem pytanie, można skorzystać z Cython owijarki scipy za Blas i procedur LAPACK. Te owijarki są udokumentowane tutaj:

Jak stwierdza dokumentacji, jesteś odpowiedzialny za sprawdzenie, czy jakieś tablice, które przechodzą do tych funkcji są ustawione prawidłowo dla Fortran rutyny. Możesz po prostu zaimportować i używać tych funkcji w razie potrzeby w pliku .pyx. Na przykład:

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

Biorąc pod uwagę, że to jest dobrze przetestowany, powszechnie stosowany kod, który działa na różnych platformach, będę argumentować, że jest to dobry kandydat na wiarygodnie dystrybucji rozszerzeń Cython że bezpośrednio wywołać Blas i rutyny Lapack .


Jeśli nie chcesz, aby Twój kod mieć zależność od całości scipy można znaleźć wiele odpowiednich dla tych plików wrappery w scipy za linalg katalogu here. Przydatnym odnośnikiem jest these lines of setup.py, który zawiera listę plików źródłowych i nagłówkowych. Zauważ, że wymagany jest kompilator Fortran!

W teoria powinno być możliwe izolowanie tylko plików źródłowych, które są potrzebne do kompilowania opakowań Cython BLAS i LAPACK, a następnie pakowanie ich jako niezależnego rozszerzenia z modułem.

W praktyce praktyka jest to bardzo kłopotliwe zadanie. Proces tworzenia modułu podrzędnego linalg wymaga niektórych funkcji Pythona, aby ułatwić kompilację na różnych platformach (np. Od here).Budowanie opiera się również na innych źródłowych plikach C i Fortran (here), których ścieżki są zakodowane na stałe w tych funkcjach Pythona.

Najwyraźniej wiele pracy zajęło sprawdzenie, czy SciPy poprawnie kompiluje się na różnych systemach operacyjnych i architekturach.

Jestem pewien, że można to zrobić, ale po przetasowaniu plików i poprawieniu ścieżek, jeszcze nie znalazłem właściwego sposobu na zbudowanie tej części modułu linalg niezależnie od reszty SciPy. Jeśli znajdę właściwą drogę, na pewno zaktualizuję tę odpowiedź.

+0

Mam wrażenie, że chodzi bardziej o to, jak połączyć blas, który jest dostarczany z scipy/numpy i czy działa on na wielu komputerach (z zainstalowanym scipy/numpy) bez konieczności ponownej kompilacji na każdym komputerze. Ale rada używania scipy dostarczanych opakowań jest dobra. – DavidW

+0

Ach, możesz tam być poprawny. Jeśli PO zapewnia dalsze wyjaśnienia, mogę zawęzić lub usunąć tę odpowiedź w razie potrzeby (lub przekształcić ją w komentarz). –

+0

To świetny sposób na zrobienie tego. @DavidW jest poprawne, że szukałem rozwiązania, które jest przenośne i nie wymaga od użytkowników instalowania dodatkowych bibliotek. Myślę, że to są rzeczy z odpowiednim plikiem setup.py. ajcr, czy możesz dodać przykład pliku setup.py pokazujący, jak uzyskać niezbędne katalogi włączające i takie? Myślę, że numpy.get_include() jest wszystkim, co jest potrzebne? – jcrudy

Powiązane problemy