2013-02-13 18 views
64

Sto scrivendo un modulo Python che include estensioni Cython e utilizza LAPACK (e BLAS). Sono aperto all'utilizzo di clapack o lapacke o di qualche tipo di soluzione f2c o f2py se necessario. Ciò che è importante è che sono in grado di chiamare le routine lapack e blas da Cython in loop stretti senza overhead di chiamata Python.Distribuzione di estensioni basate su Cython utilizzando LAPACK

Ho trovato un esempio here. Tuttavia, quell'esempio dipende da SAGE. Voglio che il mio modulo sia installabile senza installare SAGE, dal momento che i miei utenti non vogliono o hanno bisogno di SAGE per altro. È probabile che i miei utenti dispongano di pacchetti come numpy, scipy, panda e scikit installati, quindi quelli sarebbero delle dipendenze ragionevoli. Qual è la migliore combinazione di interfacce da utilizzare e quale sarebbe il file setup.py minimo che potrebbe recuperare le informazioni necessarie (da numpy, scipy, ecc.) Per la compilazione?

MODIFICA: Ecco cosa ho fatto. Funziona sul mio macbook, ma non ho idea di quanto sia portatile. Sicuramente c'è un modo migliore.

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

Questo funziona perché, sul mio MacBook, il file clapack.h intestazione è nella stessa directory cblas.h. Posso allora fare questo nel mio file pisside:

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) 

risposta

4

Se ho capito bene la domanda, si potrebbe fare uso di involucri Cython di SciPy per BLAS e routine LAPACK. Questi involucri sono documentate qui:

Come afferma documentazione, si è tenuto a verificare che tutte le matrici che si passa a queste funzioni siano allineati correttamente per le routine Fortran. Puoi semplicemente importare e utilizzare queste funzioni come necessario nel tuo file .pyx. Per esempio:

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

dato che questo è ben collaudato, il codice che viene eseguito su diverse piattaforme ampiamente usato, direi che si tratta di un buon candidato per la distribuzione in modo affidabile le estensioni Cython che chiamano direttamente BLAS e le routine LAPACK .


Se non si desidera che il codice per avere una dipendenza sulla totalità del SciPy, si possono trovare molti dei file rilevanti per queste funzioni wrapper in linalg directory di SciPy here. Un riferimento utile è these lines of setup.py che elenca i file di origine e di intestazione. Si noti che è richiesto un compilatore Fortran!

Nella teoria dovrebbe essere possibile isolare solo i file di origine qui necessari per compilare i wrapper Cython BLAS e LAPACK e quindi raggrupparli come un'estensione indipendente con il modulo.

In pratica questo è molto poco pratico da fare. Il processo di compilazione per il sottomodulo linalg richiede alcune funzioni Python per facilitare la compilazione su piattaforme diverse (ad esempio da here).Building si basa anche su altri file sorgente C e Fortran (here), i cui percorsi sono codificati in queste funzioni Python.

Ovviamente è stato fatto molto lavoro per assicurarsi che SciPy sia compilato correttamente su diversi sistemi operativi e architetture.

Sono sicuro che è possibile fare, ma dopo mischiare i file su e tweaking percorsi, non ho ancora trovato il modo giusto per costruire questa parte del modulo linalg in modo indipendente dal resto della SciPy. Se trovo il modo corretto, sono sicuro di aggiornare questa risposta.

+0

La mia impressione è che la domanda è più su come collegarsi al blas che viene fornito con scipy/numpy e farlo funzionare su più computer (con scipy/numpy installato) senza dover ricompilare su ciascun computer. Ma il consiglio di usare i wrapper forniti da scipy è buono. – DavidW

+0

Ah, potresti essere corretto lì. Se il PO fornisce ulteriori chiarimenti, posso perfezionare o rimuovere questa risposta secondo necessità (o convertirla in un commento). –

+0

Questo è un ottimo modo per farlo. @DavidW è corretto che stavo cercando una soluzione che è portatile e non richiede agli utenti di installare librerie aggiuntive. Penso che queste siano quelle cose con un file setup.py appropriato. ajcr, puoi aggiungere un esempio setup.py che mostra come ottenere qualsiasi directory di inclusione necessaria e così via? Penso che numpy.get_include() sia tutto ciò che serve? – jcrudy