Quels outils ou approches sont disponibles pour accélérer le code écrit en Python?

29

Contexte: Je pense que je pourrais vouloir porter du code qui calcule les produits matriciels à vecteur exponentiel en utilisant une méthode de sous-espace Krylov de MATLAB à Python. (Plus précisément, la fonction expmvp de Jitse Niesen , qui utilise un algorithme décrit dans cet article .) Cependant, je sais qu'à moins que j'utilise intensivement les fonctions des modules dérivés des bibliothèques compilées (c'est-à-dire que j'utilise uniquement du Python brut et pas beaucoup de dans les fonctions), cela pourrait être assez lent.

Question: Quels outils ou approches sont disponibles pour m'aider à accélérer le code que j'écris en Python pour les performances? En particulier, je m'intéresse aux outils qui automatisent le plus possible le processus, bien que les approches générales soient également les bienvenues.

Remarque: J'ai une ancienne version de l'algorithme de Jitse et je ne l'ai pas utilisée depuis un moment. Il pourrait être très facile de rendre ce code rapide, mais je pensais que ce serait un bon exemple concret, et il est lié à mes propres recherches. Débattre de mon approche pour implémenter cet algorithme particulier en Python est une autre question entièrement.

Geoff Oxberry
la source
J'ai donné une réponse spécifique à Python à cette question: scicomp.stackexchange.com/questions/2429/… Je pense que les conseils et les liens là-bas vous seront utiles.
AlexE
(h / t à @AlexE pour m'avoir informé de cela) Il y a certainement un chevauchement entre cette question, (comment) écrire des simulations plus rapides? et Quelles sont les bonnes stratégies pour améliorer les performances en série de mon code? . Une sorte de fusion pourrait être de mise. J'ai posté à ce sujet sur Meta.
Geoff Oxberry
1
En plus des bonnes réponses ici, jetez un œil à ce lien .
Mike Dunlavey

Réponses:

40

Je vais diviser ma réponse en trois parties. Profilage, accélération du code python via c et accélération de python via python. À mon avis, Python possède certains des meilleurs outils pour analyser les performances de votre code, puis remonter jusqu'aux goulots d'étranglement. Accélérer le code sans profiler, c'est comme essayer de tuer un cerf avec un uzi.

Si vous n'êtes vraiment intéressé que par les produits mat-vec, je recommanderais scipy.sparse .

Outils Python pour le profilage

modules de profil et cProfile : Ces modules vous donneront votre analyse d'exécution standard et votre pile d'appels de fonctions. Il est assez agréable d'enregistrer leurs statistiques et en utilisant le module pstats, vous pouvez consulter les données de plusieurs façons.

kernprof : cet outil rassemble de nombreuses routines pour faire des choses comme le minutage du code ligne par ligne

memory_profiler : cet outil produit une empreinte mémoire ligne par ligne de votre code.

Minuteries IPython : Latimeitfonction est assez agréable pour voir les différences de fonctions d'une manière interactive rapide.

Accélérer Python

Cython : cython est le moyen le plus rapide de prendre quelques fonctions en python et d'obtenir un code plus rapide. Vous pouvez décorer la fonction avec la variante cython de python et elle génère du code c. Ceci est très maintenable et peut également être lié à d'autres codes manuscrits en c / c ++ / fortran assez facilement. C'est de loin l'outil préféré aujourd'hui.

ctypes : ctypes vous permettra d'écrire vos fonctions en c puis de les envelopper rapidement avec sa décoration simple du code. Il gère toute la douleur du casting de PyObjects et de la gestion du gil pour appeler la fonction c.

D'autres approches existent pour écrire votre code en C mais elles sont toutes un peu plus pour prendre une bibliothèque C / C ++ et l'envelopper en Python.

Approches Python uniquement

Si vous souhaitez rester principalement dans Python, mon conseil est de déterminer quelles données vous utilisez et de choisir les types de données appropriés pour implémenter vos algorithmes. D'après mon expérience, vous obtiendrez généralement beaucoup plus loin en optimisant vos structures de données, puis tout hack c de bas niveau. Par exemple:

numpy : un tableau contingent très rapide pour les opérations stridées de tableaux

numexpr : un optimiseur d'expression de tableau numpy. Il permet des expressions de tableau numpy multithreading et supprime également les nombreuses marques temporaires de numpy en raison des restrictions de l'interpréteur Python.

blist : une implémentation b-tree d'une liste, très rapide pour l'insertion, l'indexation et le déplacement des nœuds internes d'une liste

pandas : trames de données (ou tableaux) analyses très rapides sur les tableaux.

pytables : tableaux hiérarchiques structurés rapides (comme hdf5), particulièrement adaptés aux calculs hors du noyau et aux requêtes sur des données volumineuses.

aterrel
la source
3
Vous pouvez également utiliser des ctypes pour appeler des routines Fortran.
Matthew Emmett
Ouaip
aterrel
En parlant de wrapping de code, qu'en est-il de f2py?
astrojuanlu
f2py est un excellent outil et utilisé par de nombreux membres de la communauté. fwrap est un remplacement plus récent car f2py montre son âge mais ce n'est pas vraiment complet.
aterrel
Merci! Ce sont les types de ressources que je recherchais. Je n'en connaissais que quelques-uns, et seulement en passant (ou en les regardant sur Internet). Aron continue de mentionner numexpr. Comment ça marche? Cela s'appliquerait-il?
Geoff Oxberry
7

Tout d'abord, si une implémentation C ou Fortran est disponible (fonction MATLAB MEX?), Pourquoi n'écrivez-vous pas un wrapper Python?

Si vous voulez que votre propre implémentation ne soit pas seulement un wrapper, je vous suggère fortement d'utiliser le module numpy pour des choses d'algèbre linéaire. Assurez-vous qu'il est lié à un blas optimisé (comme ATLAS, GOTOblas, uBLAS, Intel MKL, ...). Et utilisez Cython ou weave. Lisez cet article sur Python sur les performances pour une bonne introduction et une référence. Les différentes implémentations de cet article sont disponibles en téléchargement ici avec l'aimable autorisation de Travis Oliphant (Numpy-guru).

Bonne chance.

GertVdE
la source
Cet article sur Performance Python semble un peu daté, il ne mentionne pas certains des nouveaux outils disponibles comme numexpr.
Aron Ahmadia
J'ai en effet ignoré numexpr. Ce serait bien d'exécuter le même benchmark laplace avec numexpr ...
GertVdE
Est scipy.weaveencore utilisé et développé? Il semble que l'article Performance Python montre qu'il pourrait être rapide à utiliser et donne une assez bonne amélioration de la vitesse, mais je l'ai rarement vu mentionné en dehors de cet article.
Ken
@Ken: scipy.weave n'est, à ma connaissance, plus en développement actif. Il est conservé pour des raisons de compatibilité descendante, mais les nouveaux projets sont encouragés à utiliser Cython.
GertVdE
Pour GotoBLAS et NumPy / SciPy, voir der-schnorz.de/2012/06/optimized-linear-algebra-and-numpyscipy
AlexE
4

En gros, je suis d'accord avec les autres réponses. Les meilleures options pour un pythoncode numérique rapide sont

  • Utilisez des bibliothèques spécialisées comme numpy
  • envelopper votre code existant afin que votre pythonprogramme puisse l'appeler directement

Mais si vous voulez programmer l'intégralité de l'algorithme à partir de zéro (je cite: "Je n'utilise que du Python brut"), vous voudrez peut-être envisager http://pypy.org/ une implémentation JIT (Just In Time) de python. Je n'ai pas pu l'utiliser pour mon projet (car cela dépend numpyet les pypygars travaillent correctement pour le supporter) mais les benchmarks sont assez impressionnants ( http://speed.pypy.org/ )

bgschaid
la source