Quali strumenti o approcci sono disponibili per velocizzare il codice scritto in Python?


29

Background: penso che potrei voler portare un po 'di codice che calcola i prodotti a vettore esponenziale della matrice usando un metodo subspaziale Krylov da MATLAB a Python. (In particolare, la funzione expmvp di Jitse Niesen , che utilizza un algoritmo descritto in questo documento .) Tuttavia, so che a meno che non faccia un uso pesante di funzioni da moduli derivati ​​da librerie compilate (ovvero, utilizzo solo Python non elaborato e non molti built- nelle funzioni), quindi potrebbe essere piuttosto lento.

Domanda: quali strumenti o approcci sono disponibili per aiutarmi ad accelerare il codice che scrivo in Python per le prestazioni? In particolare, sono interessato agli strumenti che automatizzano il processo il più possibile, anche se gli approcci generali sono i benvenuti.

Nota: ho una versione precedente dell'algoritmo di Jitse e non la uso da un po '. Potrebbe essere molto semplice rendere veloce questo codice, ma ho pensato che sarebbe stato un buon esempio concreto ed è legato alla mia ricerca. Discutere del mio approccio per l'implementazione di questo particolare algoritmo in Python è un'altra domanda.


Ho dato una risposta settica a Python a questa domanda: scicomp.stackexchange.com/questions/2429/… Penso che i suggerimenti e i collegamenti lì ti saranno utili.
AlexE,

(h / t a @AlexE per avermi informato di questo) C'è sicuramente una sovrapposizione tra questa domanda, (come) scrivere simulazioni che funzionano più velocemente? e quali sono alcune buone strategie per migliorare le prestazioni seriali del mio codice? . Una sorta di unione potrebbe essere in ordine. Ne ho postato su Meta.
Geoff Oxberry,

1
Oltre alle buone risposte qui, dai un'occhiata a questo link .
Mike Dunlavey,

Risposte:


40

Spezzerò la mia risposta in tre parti. Creazione di profili, accelerazione del codice Python tramite C e accelerazione di Python tramite Python. Ritengo che Python disponga di alcuni dei migliori strumenti per esaminare quali sono le prestazioni del codice, quindi eseguire il drill-down fino al reale collo di bottiglia. Accelerare il codice senza profilare è come cercare di uccidere un cervo con un uzi.

Se sei davvero interessato solo ai prodotti mat-vec, consiglierei scipy.sparse .

Strumenti Python per la profilazione

Moduli profilo e cProfile : questi moduli offrono l'analisi del tempo di esecuzione standard e lo stack di chiamate delle funzioni. È abbastanza bello salvare le loro statistiche e usando il modulo pstats puoi guardare i dati in vari modi.

kernprof : questo strumento mette insieme molte routine per fare cose come il tempismo del codice riga per riga

memory_profiler : questo strumento produce impronte di memoria riga per riga del codice.

Temporizzatori IPython : latimeitfunzione è abbastanza utile per vedere le differenze nelle funzioni in modo interattivo veloce.

Accelerare Python

Cython : cython è il modo più veloce per prendere alcune funzioni in Python e ottenere codice più veloce. Puoi decorare la funzione con la variante cython di Python e genera codice c. Questo è molto stabile e può anche collegarsi ad altro codice scritto a mano in c / c ++ / fortran abbastanza facilmente. È di gran lunga lo strumento preferito oggi.

ctypes : i ctypes ti permetteranno di scrivere le tue funzioni in c e poi di avvolgerle rapidamente con la sua semplice decorazione del codice. Gestisce tutto il dolore del casting da PyObjects e gestisce il gil per chiamare la funzione c.

Esistono altri approcci per scrivere il codice in C ma sono tutti in qualche modo più adatti per prendere una libreria C / C ++ e racchiuderla in Python.

Approcci solo per Python

Se vuoi rimanere principalmente in Python, il mio consiglio è di capire quali dati stai usando e scegliere i tipi di dati corretti per l'implementazione dei tuoi algoritmi. È stata la mia esperienza che di solito aumenterai molto di più ottimizzando le tue strutture di dati rispetto a qualsiasi hack di basso livello. Per esempio:

intorpidimento : un array contingente molto veloce per operazioni a passo di matrici

numexpr : un ottimizzatore di espressioni di matrice numpy. Permette il multithreading di espressioni numpy di array e si sbarazza anche dei numerosi temporanei che numpy crea a causa delle restrizioni dell'interprete Python.

blist : un'implementazione b-tree di un elenco, molto veloce per l'inserimento, l'indicizzazione e lo spostamento dei nodi interni di un elenco

panda : frame di dati (o tabelle) analisi molto veloci sugli array.

pytables : tabelle gerarchiche strutturate rapidamente (come hdf5), particolarmente utili per calcoli fuori core e query su dati di grandi dimensioni.


3
Puoi usare i ctypes anche per chiamare le routine Fortran.
Matthew Emmett,


Parlando di wrapping code, che ne pensi di f2py?
astrojuanlu,

f2py è un ottimo strumento e utilizzato da molti nella community. fwrap è un rimpiazzo più recente in quanto f2py mostra la sua età ma non è davvero completo.
Aterrel,

Grazie! Questi sono i tipi di risorse che stavo cercando. Ne ero a conoscenza solo di alcuni, e solo di passaggio (o dal guardarli su Internet). Aron continua a menzionare numexpr. Come funziona? Sarebbe applicabile?
Geoff Oxberry,

7

Prima di tutto, se è disponibile un'implementazione C o Fortran (funzione MATLAB MEX?), Perché non scrivi un wrapper Python?

Se vuoi che la tua implementazione non sia solo un wrapper, ti consiglio vivamente di usare il modulo numpy per roba di algebra lineare. Assicurati che sia collegato a un blas ottimizzato (come ATLAS, GOTOblas, uBLAS, Intel MKL, ...). E usa Cython o intreccia. Leggi questo articolo su Performance Python per una buona introduzione e benchmark. Le diverse implementazioni in questo articolo sono disponibili per il download qui per gentile concessione di Travis Oliphant (Numpy-guru).

In bocca al lupo.


L'articolo di Performance Python sembra un po 'datato, non menziona alcuni degli strumenti più recenti disponibili come numexpr.
Aron Ahmadia,

Ho davvero trascurato numexpr. Sarebbe bello eseguire lo stesso benchmark laplace con numexpr ...
GertVdE

È scipy.weaveancora utilizzato e sviluppato? Sembra che l'articolo di Performance Python mostri che potrebbe essere veloce da usare e che dia un buon miglioramento della velocità, ma raramente l'ho visto menzionato al di fuori di quell'articolo.
Ken,

@Ken: scipy.weave, per quanto ne so, non è più in fase di sviluppo attivo. È mantenuto per compatibilità con le versioni precedenti ma i nuovi progetti sono incoraggiati a utilizzare Cython.
GertVdE,


4

Fondamentalmente sono d'accordo con le altre risposte. Le migliori opzioni per un pythoncodice numerico veloce sono

  • Utilizzare librerie specializzate come numpy
  • racchiudi il tuo codice esistente in modo che il tuo pythonprogramma possa chiamarlo direttamente

Ma se vuoi programmare l'intero algoritmo da zero (cito: "Uso solo Python grezzo"), potresti prendere in considerazione http://pypy.org/ un'implementazione JIT (Just In Time) di python. Non sono stato in grado di usarlo per il mio progetto (perché fa affidamento numpye i pypyragazzi stanno lavorando correntemente per supportarlo) ma i benchmark sono piuttosto impressionanti ( http://speed.pypy.org/ )


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.