et ensuite tu peux utiliser le module foocomme un module python normal, sauf que c'est le code natif qui s'execute
fromfooimportma_fonction# là c'est le code natif qui s'execute si foo.so est dans le pathma_fonction(range(10000),{1./iforiinxrange(1,1000)},{i,str(i)foriinrange(10)})
l'avantage c'est que même si pythran disparait de ton environnement, tu touches rien à ton code et il continue de fonctionner. Le seul changement, c'est d'isoler les parties calcul intensif dans un module, mais on pourrait presque dire que c'est pas une mauvaise pratique d'ingénierie :-)
Remarque que rien n'empêche d'écrire un décorateur @pythran qui compile à la volée, mais le temps fuit sous mon clavier, et j'ai pas eu de demandes dans ce sens pour le moment.
Si tu as un code à passer, on peut en discuter sur Freenode #pythran ou pythran@freelists.org :-)
L'info MaisQuelType == int vient de append caché dans foo. Et malheureusement je n'ai pas trouvé de moyen de faire remonter cette info au moment de l'instanciation, donc je suis obliger de mettre ça dans l'inférence de type interprocédurale… je ne sais pas si c'est plus clair comme ça ?
C'est ce que fait https://github.com/numba/numba. (du moins pour la deuxième alternative). Tu ne trouves pas ça ultra moche ? Moi si. Bon ça garde la propriété « compatible python » mais je trouve ça très intrusif.
Pour le moment on donne quelques directives pour les fonctions exportées
#pythran export fibo(int)
mais elles sont facultatives, auquel cas on génère un bon gros .h que l'utilisateur peut instancier comme il le sent. Donc on ne peut pas se servire de ses infos pour l'inférence de type.
mmmh, c'est un peu compliqué à expliquer, mais je me lance. Déjà tout est fonction, els appels de méthodes sont convertis en appels de fonctions. Prenons le cas de la fonction list.append. Les informations associées sont
elle revoie None
elle nous informe que le type de son premier paramètre self doit être compatible avec liste de . Je dis compatible parceque si on ajoute des int puis des float, au final on aura des float.
ces informations sont spécifiées en Pythran par une forme de signature de l'intrinsèque.
ensuite considérons, hors de son contexte (par exemple si la fonction n'est jamais appelée dans le module, on ne peut donc pas savoir le type des paramètres)
que faire pour append ? Je suis incapable de décider si c'est le append de list ou celui de ique. Quelles informations de type utiliser?
Vu autrement, le problème est que je veux générer des fonctions c++ polymorphiques, et donc on ne manipule ques des types symboliques ce qui fait que quand j'ai un appel de méthode, je ne sais pas (jusque l'instanciation, mais qui arrive bien plus tard) quel est le type exact des objets que je manipule, je connais juste les relations entre les types.
En théorie oui. D'ailleurs shedskin le fait.
Deux points me gênent pour le moment :
Gestion Mémoire :
En utilisant l'hypothèse types non récursifs on peut se permettre une gestion simplifiée de la mémoire (par compteurs de référence). Bon, on peut toujours refuser les classes qui induisent des dépendances de type circulaire…
Inférence de type :
Le moteur d'inférence de type de Pythran a quelques limitations. Quand je rencontre un appel de méthode, je ne sais pas à quelle classe elle est rattachée. Quand l'ensemble des méthodes (i.e. celles des conteneurs) est connu, je m'en sors très bien, mais sinon, je pense que ça va être coton.
mais la crème, c'est les variadic templates qui permettent d'implémenter de façon élégante les fonctions intrinsèques de la lib standard du genre reduce et cie…
Bah non… numpy c'est un module qui expose des structures de données optimisées (ndarray) pour le calcul scientifique et avec un coût de passage du monde python au monde natif quasi-nul et les fonctions pour travailler dessus.
Je suppose que le but c'est de pouvoir coder plus vite grâce à la simplicité de Python et générer du code C++ qui une fois compilé tournera vite ?
Oui :-) Dans la même veine que Cython, en moins intrusif
Ça veut dire qu'il n'y a plus de notion d'objet dans ton langage Python-like
C'est pas Python-like, c'est Python-embded mais c'est un détail. Tu as accès aux conteneurs de base (list/set/dict/tuple), à terme file, mais pas de classes utilisateurs. Tu peux avoir des classes au dessus (dans la partie non Pythran) et appeler le module devenu natif pour les parties gourmandes en calcul. Le but n'est pas de traduire tout Python, juste les parties gourmandes, qui n'ont pas forcément besoin de classe, comme l'illustre le lien sur le gars qui répond aux devinettes du projet euler sans utiliser de classes.
Par exemple on a récemment convertit un petit code de simulation (~300SLOC), pas de classes, et un speedup de x50 à la clef.
Si on est prêt à utiliser les extensions GNU, asprintf fait des merveilles. Sinon, il y a la gnulib qui apporte la couche de portabilité manquante et qui s'intègre merveilleusement bien à un build autotool.
C'est un convertisseur d'un sous ensemble de python vers du C++. En gros en enlevant les classes utilisateurs et tous les aspects trop dynamiques, on arrive à convertir des codes de calcul en des codes relativement efficace (cf. benchs dans le journal). Le README du projet est, je l'espère, plus explicite ?
Salut,
super rretour! Pas plus tard qu'hier je me décidais à écrire la version OpenMP d'un matrix mutliply en pythran, que je vous livre ci-dessous:
#pythran export matrix_multiply(float list list, float list list)defzero(n,m):return[[0forrowinxrange(n)]forcolinxrange(m)]defmatrix_multiply(m0,m1):new_matrix=zero(len(m0),len(m1[0]))"omp parallel for private(i,j,k)"foriinxrange(len(m0)):forjinxrange(len(m1[0])):forkinxrange(len(m1)):new_matrix[i][j]+=m0[i][k]*m1[k][j]returnnew_matrix
Pythran ne fait pas de privatisation de variable, elles sont toutes déclarées à l'entrée de la fonction (comme en FORTRAN :p), donc mettre le mode defauls(none) me semble tout particulièrement indiqué !
Le problème ici est que le mode par défaut est shared, sauf pour l'indice de la boucle sur laquelle porte la directive et donc les variables i2 et i3 seront mises en mémoire partagées et là c'est le drame.
Quand on fait du C++/C99 un peu propre, on préfère la forme
J'y avais pensé, mais sans le @, donc un truc du genre
defsaxpy(x,y,a):#omp parallel for private(i,b)foriinrange(len(x)):b=a*x[i]# laid mais utile pour l'exempley[i]+=b
Le problème c'est que les commentaires sont jetés par le parseur python (du moins celui fourni dans le module standard: ast), ce qui n'est pas le cas des chaîne de caractère.
Dans la famille hack sympathique il suffirait d'un bon vieux
sed -r -e 's/^(\s*)#omp( .*)$/1円"omp2円"/g'
pour s'en sortir, ou l'équivalent en utilisant re.sub. Mais c'est pas très robuste.
pour les fins de lignes, j'ai l'habitude de formater mon post dans un vim externe, qui m'aligne tout (enfin pas tout justement…) à +/- 80 caractère par colonne. Et ce billet montre que je me suis lourdé royal :-)
Pour les débuts/fins de bloc, c'est effectivement la convention adoptée par OpenMP pour le Fortran, c'est très roleplay de faire comme ça en effet.
On dirait que les softeux ont toujours autant de mal avec le hardware.
Ça c'est sûr :-) trois années passées à m'y frotter (le moins possible) n'ont malheureusement pas apportées de grands changements :-(
le nombre de transistors d'une puce double tous les 18 mois/ 2 ans pour le même prix.
Il me semblait que c'était à surface constante, d'où problème de « mur de la chaleur » etc. Pareillement les moulti-cœurs ne changent rien au problème d'intégration.
C'est surtout une histoire de cout de développement qui explose.
Oui. La difficulté de programmation de l'archi n'y est pas étrangère, puisqu'il faut embaucher des développeurs spécialisés au lieu de développeurs généralistes.
Pour le moment, j'ai des compteurs de références sur chacun des conteneurs (liste / ensemble uniquement donc). Comme il n'y a pas de classes utilisateur, je ne pense pas qu'il soit possible de créer des références croisées.
Dans ce cas, on peut quand même s'en sortir en déléguant l'évaluation de la condition à l'exécution, ce qui a quelques défauts (dont augmentation de la taille du code) mais pas mal d'avantages aussi.
Un cas classique pour gérer l'aliasing:
#include <stdint.h>voidfoo(size_tn,floata[n],floatb[n]){// aucune garantie que a et b ne se chevauchent pas partiellement ou totalementfor(size_ti=1;i<n;i++){// cette boucle n'est parallèle que si a et b ne se chevauchent pasa[i]=2*b[i-1];}
Dans ce cas un petit test dynamique permet de suppléer aux carences de l'analyse statique
Cela simplifie grandement la génération de code, le debug etc. D'après les test faits jusqu'à présent, c'est pas dégueux niveaui perf non plus :-)
pythran vise à être compatible OpenMP (à faire à faire, ça devrait être prêt pour les PyconFR). Et là encore c'est plus facile à faire au niveau source qu'au niveau bytecode
Sinon lire l'excellente thèse de Serge Guelton sur les atouts de la compilation source-à-source ;-)
[^] # Re: Plus de classes
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 1.
Pour le moment, tu prends un module python, disons
foo.py, tu l'annotes légèrementpuis
et ensuite tu peux utiliser le module
foocomme un module python normal, sauf que c'est le code natif qui s'executel'avantage c'est que même si pythran disparait de ton environnement, tu touches rien à ton code et il continue de fonctionner. Le seul changement, c'est d'isoler les parties calcul intensif dans un module, mais on pourrait presque dire que c'est pas une mauvaise pratique d'ingénierie :-)
Remarque que rien n'empêche d'écrire un décorateur
@pythranqui compile à la volée, mais le temps fuit sous mon clavier, et j'ai pas eu de demandes dans ce sens pour le moment.Si tu as un code à passer, on peut en discuter sur Freenode #pythran ou pythran@freelists.org :-)
[^] # Re: Plus de classes
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 4.
Oui, oui, je fais déjà tout ça. Mon exemple n'était pas bon
traduit comme tu le proposes ça donnerait
L'info
MaisQuelType == intvient deappendcaché dans foo. Et malheureusement je n'ai pas trouvé de moyen de faire remonter cette info au moment de l'instanciation, donc je suis obliger de mettre ça dans l'inférence de type interprocédurale… je ne sais pas si c'est plus clair comme ça ?[^] # Re: Plus de classes
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 2.
C'est ce que fait https://github.com/numba/numba. (du moins pour la deuxième alternative). Tu ne trouves pas ça ultra moche ? Moi si. Bon ça garde la propriété « compatible python » mais je trouve ça très intrusif.
Pour le moment on donne quelques directives pour les fonctions exportées
mais elles sont facultatives, auquel cas on génère un bon gros .h que l'utilisateur peut instancier comme il le sent. Donc on ne peut pas se servire de ses infos pour l'inférence de type.
[^] # Re: Plus de classes
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 1.
mmmh, c'est un peu compliqué à expliquer, mais je me lance. Déjà tout est fonction, els appels de méthodes sont convertis en appels de fonctions. Prenons le cas de la fonction
list.append. Les informations associées sontNoneselfdoit être compatible avec liste de . Je dis compatible parceque si on ajoute desintpuis desfloat, au final on aura desfloat.ces informations sont spécifiées en
Pythranpar une forme de signature de l'intrinsèque.ensuite considérons, hors de son contexte (par exemple si la fonction n'est jamais appelée dans le module, on ne peut donc pas savoir le type des paramètres)
que faire pour append ? Je suis incapable de décider si c'est le append de
listou celui deique. Quelles informations de type utiliser?Vu autrement, le problème est que je veux générer des fonctions c++ polymorphiques, et donc on ne manipule ques des types symboliques ce qui fait que quand j'ai un appel de méthode, je ne sais pas (jusque l'instanciation, mais qui arrive bien plus tard) quel est le type exact des objets que je manipule, je connais juste les relations entre les types.
[^] # Re: Plus de classes
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 1.
En théorie oui. D'ailleurs shedskin le fait.
Deux points me gênent pour le moment :
Gestion Mémoire :
En utilisant l'hypothèse types non récursifs on peut se permettre une gestion simplifiée de la mémoire (par compteurs de référence). Bon, on peut toujours refuser les classes qui induisent des dépendances de type circulaire…
Inférence de type :
Le moteur d'inférence de type de
Pythrana quelques limitations. Quand je rencontre un appel de méthode, je ne sais pas à quelle classe elle est rattachée. Quand l'ensemble des méthodes (i.e. celles des conteneurs) est connu, je m'en sors très bien, mais sinon, je pense que ça va être coton.[^] # Re: C++ oui mais pourquoi ?
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 7.
Oui ! Plus précisément
Pour la lib standard
list->std::vectorset->std::unordered_setdict->std::unordered_maptuple->std::tuple(assez costaud celui là)print(truc, muche)->std::cout << truc << ' ' << muchePour l'inférence de type
decltypeetdeclvalfont des merveillesPour la gestion mémoire
vive les
std::shared_ptrPetit exemple
qui devient (en simplifiant)
La crème de la crème
mais la crème, c'est les variadic templates qui permettent d'implémenter de façon élégante les fonctions intrinsèques de la lib standard du genre
reduceet cie…[^] # Re: Intéressant
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 1.
C'est ça.
Nous apprend qu'il y a des dépendances sur
libgfortran3,libblas3gf | libblas.so.3gf | libatlas3gf-basece qui annonce un peu la couleur :-)[^] # Re: Intéressant
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 1.
Bah non… numpy c'est un module qui expose des structures de données optimisées (
ndarray) pour le calcul scientifique et avec un coût de passage du monde python au monde natif quasi-nul et les fonctions pour travailler dessus.[^] # Re: Intéressant
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pythran : C++ pour les serpents. Évalué à 2.
Oui :-) Dans la même veine que Cython, en moins intrusif
C'est pas Python-like, c'est Python-embded mais c'est un détail. Tu as accès aux conteneurs de base (
list/set/dict/tuple), à termefile, mais pas de classes utilisateurs. Tu peux avoir des classes au dessus (dans la partie non Pythran) et appeler le module devenu natif pour les parties gourmandes en calcul. Le but n'est pas de traduire tout Python, juste les parties gourmandes, qui n'ont pas forcément besoin de classe, comme l'illustre le lien sur le gars qui répond aux devinettes du projet euler sans utiliser de classes.Par exemple on a récemment convertit un petit code de simulation (~300SLOC), pas de classes, et un speedup de x50 à la clef.
# asprintf
Posté par serge_sans_paille (site web personnel) . En réponse au journal Genèse d'un journal. Évalué à 3.
Si on est prêt à utiliser les extensions GNU,
asprintffait des merveilles. Sinon, il y a la gnulib qui apporte la couche de portabilité manquante et qui s'intègre merveilleusement bien à un build autotool.[^] # Re: Super naze
Posté par serge_sans_paille (site web personnel) . En réponse au journal Échec et mat. Évalué à 1.
Zut, j'aime bien faire des pompes moi…
[^] # Re: saikoi ?
Posté par serge_sans_paille (site web personnel) . En réponse au journal pythran prépare sa mue. Évalué à 2.
Merci de me faire découvrir la PEP20 !
Pour pythran c'est… bien :-)
C'est un convertisseur d'un sous ensemble de python vers du C++. En gros en enlevant les classes utilisateurs et tous les aspects trop dynamiques, on arrive à convertir des codes de calcul en des codes relativement efficace (cf. benchs dans le journal). Le README du projet est, je l'espère, plus explicite ?
[^] # Re: OpenMP et la fausse simplicité...
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pyth(on|ran) + OpenMP ?. Évalué à 2.
Salut,
super rretour! Pas plus tard qu'hier je me décidais à écrire la version OpenMP d'un matrix mutliply en pythran, que je vous livre ci-dessous:
Pythran ne fait pas de privatisation de variable, elles sont toutes déclarées à l'entrée de la fonction (comme en FORTRAN :p), donc mettre le mode defauls(none) me semble tout particulièrement indiqué !
1000 fois merci :-)
[^] # Re: OpenMP et la fausse simplicité...
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pyth(on|ran) + OpenMP ?. Évalué à 2.
Ça veut dire que toute les variables référencée dans la boucle doivent avoir une visibilité spécifiée dans la directive, sinon erreur de compilation.
[^] # Re: OpenMP et la fausse simplicité...
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pyth(on|ran) + OpenMP ?. Évalué à 3.
Le problème ici est que le mode par défaut est
shared, sauf pour l'indice de la boucle sur laquelle porte la directive et donc les variables i2 et i3 seront mises en mémoire partagées et là c'est le drame.Quand on fait du C++/C99 un peu propre, on préfère la forme
qui ne pose pas de soucis car les variables locales sont considérées comme
privateLa lecture de http://en.wikipedia.org/wiki/OpenMP#Data_sharing_attribute_clauses est un bon point de départ pour comprendre ça.
[^] # Re: Avec un with ?
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pyth(on|ran) + OpenMP ?. Évalué à 3.
C'est un détournement assez amusant et intéressant du
withça. J'aime !Plus ou moins. ça force à ajouter un
import pythran.Pragmadans le module, et ce n'est pas trop dans l'esprit…Sinon on pourrait raffiner ta proposition et avoir un manager pour
parallelou pourtasket ainsi de suite. Mais ça commence à être verbeux.[^] # Re: Des annotations en commentaire
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pyth(on|ran) + OpenMP ?. Évalué à 4.
J'y avais pensé, mais sans le
@, donc un truc du genreLe problème c'est que les commentaires sont jetés par le parseur python (du moins celui fourni dans le module standard:
ast), ce qui n'est pas le cas des chaîne de caractère.Dans la famille hack sympathique il suffirait d'un bon vieux
pour s'en sortir, ou l'équivalent en utilisant
re.sub. Mais c'est pas très robuste.[^] # Re: [HS] Tu l'as écrit sur une vieille machine à écrire
Posté par serge_sans_paille (site web personnel) . En réponse au journal Pyth(on|ran) + OpenMP ?. Évalué à 3.
pour les fins de lignes, j'ai l'habitude de formater mon post dans un vim externe, qui m'aligne tout (enfin pas tout justement…) à +/- 80 caractère par colonne. Et ce billet montre que je me suis lourdé royal :-)
Pour les débuts/fins de bloc, c'est effectivement la convention adoptée par OpenMP pour le Fortran, c'est très roleplay de faire comme ça en effet.
[^] # Re: C'est très connu
Posté par serge_sans_paille (site web personnel) . En réponse au journal Python et valeurs par défaut des paramètres. Évalué à 4.
En tout cas c'est dans le tutoriel officiel.
Comme quoi l'apprentissage par induction dont je suis friand a ses limites :-).
[^] # Re: J'aime pas ce comportement
Posté par serge_sans_paille (site web personnel) . En réponse au journal Python et valeurs par défaut des paramètres. Évalué à 0.
Oui, j'ai vu cet idiome de nombreuses fois. Ça ressemble furieusement à ça http://en.wikipedia.org/wiki/Option_type.
[^] # Re: LLVM
Posté par serge_sans_paille (site web personnel) . En réponse au journal pythran rampe. Évalué à 1.
Ça c'est sûr :-) trois années passées à m'y frotter (le moins possible) n'ont malheureusement pas apportées de grands changements :-(
Il me semblait que c'était à surface constante, d'où problème de « mur de la chaleur » etc. Pareillement les moulti-cœurs ne changent rien au problème d'intégration.
Oui. La difficulté de programmation de l'archi n'y est pas étrangère, puisqu'il faut embaucher des développeurs spécialisés au lieu de développeurs généralistes.
[^] # Re: LLVM
Posté par serge_sans_paille (site web personnel) . En réponse au journal pythran rampe. Évalué à 1.
Pour le moment, j'ai des compteurs de références sur chacun des conteneurs (liste / ensemble uniquement donc). Comme il n'y a pas de classes utilisateur, je ne pense pas qu'il soit possible de créer des références croisées.
Ça suffit, non ?
[^] # Re: allocation de tableau
Posté par serge_sans_paille (site web personnel) . En réponse au journal pythran rampe. Évalué à 2.
Dans ce cas, on peut quand même s'en sortir en déléguant l'évaluation de la condition à l'exécution, ce qui a quelques défauts (dont augmentation de la taille du code) mais pas mal d'avantages aussi.
Un cas classique pour gérer l'aliasing:
Dans ce cas un petit test dynamique permet de suppléer aux carences de l'analyse statique
iccfait ça à fond ![^] # Re: LLVM
Posté par serge_sans_paille (site web personnel) . En réponse au journal pythran rampe. Évalué à 1.
Il y a déjà pymothoa qui vise à faire ça.
Deux arguments pour la génération de C++:
Cela simplifie grandement la génération de code, le debug etc. D'après les test faits jusqu'à présent, c'est pas dégueux niveaui perf non plus :-)
pythran vise à être compatible OpenMP (à faire à faire, ça devrait être prêt pour les PyconFR). Et là encore c'est plus facile à faire au niveau source qu'au niveau bytecode
Sinon lire l'excellente thèse de Serge Guelton sur les atouts de la compilation source-à-source ;-)
[^] # Re: LLVM
Posté par serge_sans_paille (site web personnel) . En réponse au journal pythran rampe. Évalué à 1.
D'après la doc pypy tu as raison.