Termi' Nal (humour du 42ème degré),
Pythran compilateur open source dédié au Python scientifique, a sorti sa version 0.7 il y a peu, à l'occasion du premier événement PyData organisé en France: PyData Paris. ±6 mois s'étaient écoulés depuis la dernière sortie de ce compilateur dont vous pouvez suivre les aventures trépidantes à travers le tag pythran.
- Site du projet
- Sur GitHub
- Sur Pypi
- Présentation à Pydata en franglais
Nouveautés
- Meilleur support de Numpy, plus de fonctions, et une meilleur implémentations pour certaines d'entre elles.
- Meilleur support de l'indicage étendu, y compris les aberrations du genre a[-1:1:2,:,3][4]
- Effort sur l'interface utilisateur (messages d'erreurs lors des échecs de compilation ou d'installation)
- Support du stockage FORTRAN style et pas seulement C style pour les tableaux en entrée de Pythran
- Analyse (succincte, mais quand même) de la plage de valeur prise par certaines variables pour faire sauter certains tests
Communauté
La grosses surprise de cette version, c'est d'avoir reçu de nombreuses contributions extérieures non francophones. Principalement des rapports de bugs (on va pas dire des rapports de vermine, ce ne serait pas poli). Support archlinux, retours sur l'indicage, les expressions masque et leurs performances, le support de linalg…
C'est vraiment super motivant. Imaginez qu'actuellement du code compilé par Pythran tourne sur un petit robot autonome sous-marin en mer du nord ! C'est la folie !
La franchouillarde société Numscale non contente de nous fournir un moteur de Ferarri avec la lib C++ NT², met aussi des heures de dev pour un portage sous Windows, ce qui améliore la portabilité du code généré, mais demande des, disons, ajustements pour palier au support partiel de C++11 par VS20XY.
D'ailleurs mon alter ego Pierrick Brunet, qui s'est déchiré pour cette release, cherche du boulot. Contactez le !
Cas concret
Jetez un coup d'œil à ce sympathique code source tiré de stackoverflow :
import numpy as np
def GrayScott(counts, Du, Dv, F, k):
n = 300
U = np.zeros((n+2,n+2), dtype=np.float32)
V = np.zeros((n+2,n+2), dtype=np.float32)
u, v = U[1:-1,1:-1], V[1:-1,1:-1]
r = 20
u[:] = 1.0
U[n/2-r:n/2+r,n/2-r:n/2+r] = 0.50
V[n/2-r:n/2+r,n/2-r:n/2+r] = 0.25
u += 0.15*np.random.random((n,n))
v += 0.15*np.random.random((n,n))
for i in range(counts):
Lu = ( U[0:-2,1:-1] + U[1:-1,0:-2] - 4*U[1:-1,1:-1] + U[1:-1,2:] + U[2: ,1:-1] )
Lv = ( V[0:-2,1:-1] + V[1:-1,0:-2] - 4*V[1:-1,1:-1] + V[1:-1,2:] + V[2: ,1:-1] )
uvv = u*v*v
u += Du*Lu - uvv + F*(1 - u)
v += Dv*Lv + uvv - (F + k)*v
return V
Il compile désormais avec Pythran en ajoutant l'annotation
#pythran export GrayScott(int, float, float, float, float)
et c'est une grande victoire, car il représente bien ce qu'on peut trouver comme type de code Python/numpy :
- des appels de fonction externe
numpy.random.random
- de l'indicage étendu à gogo
u, v = U[1:-1,1:-1], V[1:-1,1:-1]
et même composé avecu[:] = 1.0
- une boucle externe explicite qui entoure des boucles implicites (cf. les calculs de
Lu
etLv
)
Donc arriver à compiler ça sans demander à l'utilisateur d'expliciter les calculs comme il faudrait le faire en Cython, c'est chouette !
Les perfs sont d'ailleurs au rendez vous !
$ python -m timeit -s 'from grayscott import GrayScott' 'GrayScott(40, 0.16, 0.08, 0.04, 0.06)'
10 loops, best of 3: 52.9 msec per loop
$ cython grayscott.pyx
$ gcc grayscott.c `python-config --cflags --libs` -shared -fPIC -o grayscott.so -O3 -march=native
$ python -m timeit -s 'from grayscott import GrayScott' 'GrayScott(40, 0.16, 0.08, 0.04, 0.06)'
10 loops, best of 3: 36.4 msec per loop
$ pythran grayscott.py -O3 -march=native
$ python -m timeit -s 'from grayscott import GrayScott' 'GrayScott(40, 0.16, 0.08, 0.04, 0.06)'
10 loops, best of 3: 20.3 msec per loop
La suite
Au prochain opus, forcément, avec certainement le support de numpy.linalg
et numpy.random
!
Pythran — C++ for snakes
# micro bench dans une loupe
Posté par Nicolas Boulay (site web personnel) . Évalué à 10.
J'ai juste une remarque sur ton bench : "10 boucles et moyennes de 3 meilleurs".
Si tu traces une courbe des temps d’exécution de chaque boucle, tu verras un temps décroissant sur les 3 ou 4 premières exécution puis un plateau, et parfois des pics (allocation mémoire, switch de contexte…).
En fait, tu remplit tes caches, et ensuite, ils sont "chaud", le code est ainsi le plus rapide. Mais c'est loin de la réalité. Dans la réalité, tu ne ré-exécutes jamais le même code sur les même données 2 fois de suite.
Ce genre de bench ne permet pas d'estimer tout code d'optimisation d'usage du cache (tiling, accès linéaire à la mémoire,…).
A l'inverse, si tu nettoies complètement les caches (boucles entre 2 exécutions sur des données externes). Tu te places dans un pire cas : le cache "froid". Ce n'est peut être pas non plus réaliste.
Dans tous les cas, je préfère utiliser une courbe (ici tu aurais 10 points). Tu as 3 cas, donc 3 courbes. Tu peux voir l'efficacité de la 1er exécution, l'augmentation de perf ensuite, et visualiser tous problèmes avec les données (point aberrant dû à changement de contexte par exemple)
"La première sécurité est la liberté"
[^] # Re: micro bench dans une loupe
Posté par serge_sans_paille (site web personnel) . Évalué à 3.
Tu as raison ! Les choix faits par
timeit
nous donnent uniquement une info de type performance de crête, pas grand chose sur les effets de cache et rien sur la variabilité.[^] # Re: micro bench dans une loupe
Posté par lasher . Évalué à 3.
Tu as raison pour les micro-benches, mais si d'un côté tu ne vas sans doute pas exécuter 10000 fois le même noyau de code d'affilée, tu vas par contre réutiliser les mêmes structures de données régulièrement, en leur faisant subir plusieurs types de traitements. De ce côté-là, ça signifie que oui, tu auras au moins une partie des structures de données présentes dans les caches.
Personnellement j'aime faire les deux :
Dans le cas précis de Python, c'est beaucoup plus compliqué, car le ramasse-miettes, les mécanismes dynamiques de typage, etc., font que des traitements annexes au code lui-même peuvent se déclencher de façon complètement imprévisible.
[^] # Re: micro bench dans une loupe
Posté par Nicolas Boulay (site web personnel) . Évalué à 3.
Oui, dans la réalité le cache n'est ni chaud ni froid, mais tiède (sauf donnés >10Mo). L'idéal est de bencher un code réel.
En général, je teste le pire cas : cache froid (== cela sera toujours plus rapide en vrai, et tu vois les effets d'optimisation type tilling). Je fais une courbe, et jamais de moyenne, cela permet de voir visuellement tous les effets que tu cites en python (gc…).
"La première sécurité est la liberté"
# Question naïve
Posté par Joalland . Évalué à 0.
Attention, question vraiment naïve d'un noob :
Les logiciels de calcul matriciels genre Scilab ne sont-ils pas plus optimisés pour ce genre de calcul ?
Moi qui fais de temps en temps du calcul "scientifique" je trouve gonflant de devoir déclarer le type de mes valeurs lorsque je le fais avec un "langage de programmation".
Puis devoir taper sans-cesse le nom des modules pour les fonctions usuels genre math.floor() math.ceil(), np.exp(), bref je ne trouve pas ça pratique.
Quels sont donc les avantages du travail scientifique en python ?
[^] # Re: Question naïve
Posté par Marotte ⛧ . Évalué à 3.
Si au lieu de faire :
tu fais :
Tu pourra taper directement floor(), ceil(), etc…
[^] # Re: Question naïve
Posté par Maxime (site web personnel) . Évalué à 4.
(je parle uniquement de Python ici et non de Pythran)
L'intérêt du Python c'est justement de pouvoir s'en passer…
Je ne fais pas souvent du calcul scientifique mais Matlab &co ont une syntaxe que je trouve plus complexe à comprendre que le Python (subjectif mais ça satisfait les gens de mon avis). Autre point, si tu développes un logiciel scientifique, tu peux développer tout le logiciel en Python et faire des appels à Numpy lorsque c'est nécessaire. C'est quand même sympa de pouvoir développer l'interface graphique avec Qt par exemple.
Et puis vu que tes 2 critiques ne sont pas justifiées (pas besoin de remettre le nom du module à chaque appel de fonction et typage dynamique), on pourrait inverser la question : Quels sont les avantages du travail scientifique avec Scilab ?
# Fonctions de haut niveau
Posté par paco81 . Évalué à 1.
Je suis ton projet avec un grand intérêt, j'aime beaucoup l'approche (et les résultats !).
Je me demandais si il y a un espoir, à l'avenir, de pouvoir utiliser des fonctions de plus "haut niveau" comme des fonctions scipy (par exemple scipy.optimize.minimize). Quelles sont les limites ?
[^] # Re: Fonctions de haut niveau
Posté par serge_sans_paille (site web personnel) . Évalué à 2.
merci :-)
il y a quelques limites liées au typage : impossible dans le modèle Pythran actuel de supporter les fonctions qui ne sont pas implicitement statiquement typées. Par exemple un truc du genre :
ensuite pour les fonctions scipy, on pourrait espérer qu'une fois le support de numpy suffisamment abouti, ça se fasse automagiquement pour celles qui ne sont pas implémentées en natif. Mais la route est encore longue, bien que certaines genre
https://github.com/scipy/scipy/blob/v0.15.1/scipy/optimize/optimize.py#L154
passeraient sans soucis.
# cython
Posté par François (site web personnel) . Évalué à 1.
Salut et bravo pour ce travail. Sinon comme je commence à m'intéresser de près à cython, est ce que tu pourrais expliciter un peu plus cette phrase
[^] # Re: cython
Posté par serge_sans_paille (site web personnel) . Évalué à 2.
Cython n'optimise pas les appels à des fonctions numpy. Tu peux lire le fil stackoverflow dont est extrait l'exemple donné dans le journal pour voir la « meilleur solution » cython proposée et te convaincre que c'est un peu une régression :-)
# Python 3 ?
Posté par jihele . Évalué à 4.
Merci, je ne connaissais pas Pythran.
Le support Python 3 est il envisagé ?
Je vois que qqn sur GitHub a déjà demandé que le code compilé depuis Python 2.7 puisse être importé en Python 3, mais je pense aussi à la compilation de code Python 3.
[^] # Re: Python 3 ?
Posté par serge_sans_paille (site web personnel) . Évalué à 3.
Salut,
il y a plusieurs niveaux de support possible
et toute combinaison de ces trois fonctionnalités. Pour le moment, aucune n'est supportée, on a eu assez peu de demande autour de ça, je l'avoue. Et ce n'est pas si évident car l'AST et la sémantique du langages changent entre les deux… il ne suffit pas de mettre des parenthèses dans les
print
;-)Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.