Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Élimination d'allocations temporaires en Python Alan Raynaud Encadré par Serge Guelton Projet de n d'étude Telecom-Bretagne 6èmes rencontres de la communauté française de compilation Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Plan de la présentation 1 Contexte 2 Détection des allocations temporaires inutiles 3 Application à Pythran 4 Conclusion 1.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 Plan de la présentation 1 Contexte Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 2 Détection des allocations temporaires inutiles Objectif Annotation de l'AST Analyse interprocédurale Résumé 3 Application à Pythran Pythran Application Résultats 2.0 4 Conclusion Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 Description (informelle) d'un générateur Un générateur est un objet se comportant comme un itérateur, mais qui créé ses valeurs à la volée. 3.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 Exemple def s q u a r e ( n ) : for index in yield def range (n ) : n∗n foo (n ) : sum ( s q u a r e ( n ) ) 4.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 List Comprehension et Generator Expression Syntaxe concise permettant de créer des listes ou des générateurs. List Comprehension : [x ∗ x for x in range (n ) ] Generator Expression : (x ∗ x for x in range (n )) 5.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Les générateurs de Python Détection des allocations temporaires inutiles Le module Application à Pythran Le module itertools itertools pour Python 2.X Le cas Python 3 Conclusion Le module itertools contient des générateurs pouvant être utilisés et combinés dans un programme Python. imap est équivalent à map ( lambda > x est équivalent à zip ([1 ,2 ,3] , [(1 ,4) , ifilter x, [0 ,1 ,2 ,3 ,4]) zip [4 ,5 ,6]) (2 ,5) , (3 ,6)] est équivalent à f i l t e r ( lambda > ∗ x [0 ,1 ,4 ,9 ,16] izip > : map x : filter x < 5, [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8]) [1 ,2 ,3 ,4] 6.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 Performances Somme des x2 pour x entre 1 et N 0.018 Using map Using imap 0.016 0.014 Temps d’execution 0.012 0.01 0.008 0.006 0.004 0.002 0 0 10000 20000 30000 40000 50000 N 60000 70000 80000 90000 100000 7.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 Python 3 Version de Python volontairement incompatible avec Python 2. Changement notable : map, zip, lter et range renvoient des générateurs et non plus des listes. L'outil 2to3 eectue une conversion automatique mais peu optimisée. 8.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 Python 3 Version de Python volontairement incompatible avec Python 2. Changement notable : map, zip, lter et range renvoient des générateurs et non plus des listes. L'outil 2to3 eectue une conversion automatique mais peu optimisée. def f o o ( n ) : return z i p ( range (n ) , range (n )) devient def f o o ( n ) : return l i s t ( z i p ( l i s t ( range (n )) , l i s t ( range (n ) ) ) ) 8.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Plan de la présentation 1 Contexte Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 2 Détection des allocations temporaires inutiles Objectif Annotation de l'AST Analyse interprocédurale Résumé 3 Application à Pythran Pythran Application Résultats 4 Conclusion 9.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Détection des allocations temporaires inutiles Il y a une allocation temporaire inutile si on peut remplacer une expression produisant une liste par un générateur. 10.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Détection des allocations temporaires inutiles Il y a une allocation temporaire inutile si on peut remplacer une expression produisant une liste par un générateur. Objectif Détecter les expressions pouvant êtres remplacées par un générateur. 10.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Méthode On parcourt l'AST (Abstract Syntax Tree) du programme Python. On va chercher à annoter les noeuds de l'AST avec une information du type Peut être remplacé par un générateur 11.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cas simples(1) for e in iter : foo ( e ) AST : For(expr target, expr iter, stmt* body, stmt* orelse) 12.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cas simples(1) for e in iter : foo ( e ) AST : For(expr target, expr iter, stmt* body, stmt* orelse) On peut toujours annoter le noeud iter. 12.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cas simples(2) b1 = 5 b2 = 5 in range (10) not i n r a n g e ( 1 0 ) AST : Compare(expr left, cmpop op, expr comparator) 13.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cas simples(2) b1 = 5 b2 = 5 in range (10) not i n r a n g e ( 1 0 ) AST : Compare(expr left, cmpop op, expr comparator) Si op = In ou NotIn, on peut annoter comparator. 13.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cas moins simple foo (a , b , c ) AST : Call(expr func, expr* args, keyword* keywords, expr? starargs, expr? kwargs) 14.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cas moins simple foo (a , b , c ) AST : Call(expr func, expr* args, keyword* keywords, expr? starargs, expr? kwargs) Problème : comment savoir si les arguments peuvent être remplacés par des générateurs ? 14.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Eets des fonctions sur leurs arguments Proposition : Un argument passé à une fonction peut être remplacé par un générateur s'il n'est jamais modié et s'il est lu au plus une fois. 15.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Eets des fonctions sur leurs arguments Proposition : Un argument passé à une fonction peut être remplacé par un générateur s'il n'est jamais modié et s'il est lu au plus une fois. Objectif Déterminer les arguments vériant ce critère pour chaque fonction. 15.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Fonction de poids On va dénir une fonction de poids qui renvoie le nombre de lecture d'un paramètre formel d'une fonction donnée. u(foo, narg) = nombre de lecture du narg-ieme paramètre formel de foo 16.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Objectif Détection des allocations temporaires inutiles Annotation de l'AST Application à Pythran Analyse interprocédurale Conclusion Résumé Cas des intrinsèques Pour les intrinsèques, on dénit une table donnant explicitement le poids des arguments. 17.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Objectif Détection des allocations temporaires inutiles Annotation de l'AST Application à Pythran Analyse interprocédurale Conclusion Résumé Cas des intrinsèques Pour les intrinsèques, on dénit une table donnant explicitement le poids des arguments. Exemple : u(map,1) = 1 17.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Fonctions utilisateur Méthode : On parcourt l'AST de la dénition de fonction pour construire la fonction de poids à partir des poids de chaque noeuds. 18.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Fonctions utilisateur Méthode : On parcourt l'AST de la dénition de fonction pour construire la fonction de poids à partir des poids de chaque noeuds. Une fois la construction de fonction de poids terminée, on peut l'évaluer pour obtenir les poids des arguments des fonctions. 18.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Exemple def f o o ( n , l 1 , l 2 ) : i f ( n <5): for x in l 1 : bar ( x , l 2 ) else : bar (0 , l 2 ) If(cond, body, else) : cond + max(body, else) 1 if narg == 0 else 1 For(iter,body) : iter + MAX * body 1 if narg == 1 else 0 u(bar,1) if narg == 2 else 0 u(bar,1) if narg == 2 else 0 19.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Cycles et recursivité Pour détecter les cycles, on mémorise le chemin lors de l'évaluation. (suite des appels à une autre fonction de poids). Exemple : foo -> bar -> jo -> foo -> ... On estime le poids total du cycle de la façon suivante : Poids total = MAX * poids partiel 20.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Objectif Annotation de l'AST Analyse interprocédurale Résumé Resumé 1 On calcule les fonctions de poids : directement pour les intrinsèques, en parcourant l'AST pour les fonctions utilisateur. 2 On évalue les poids des arguments de toutes les fonctions. 3 On annote l'AST : directement pour les noeuds NotIn, In, et For. Si le poids est <=1 pour les arguments des noeuds Call. 21.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Plan de la présentation 1 Contexte Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 2 Détection des allocations temporaires inutiles Objectif Annotation de l'AST Analyse interprocédurale Résumé 3 Application à Pythran Pythran Application Résultats 4 Conclusion 22.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Pythran en bref Pythran : Traduit un sous-ensemble de Python vers C++ Génère des modules utilisables depuis Python Permet la parallélisation des opérations en utilisant des directives openMP. 23.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Chaine de compilation OpenMP Python Module [.py] Type Info Pythran boost::python C++ pythonic++ g++ Native Module [.so] Alan Raynaud 24.0 Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Pertinence Somme des x2 pour x entre 1 et N 0.0045 En utilisant map En utilisant imap 0.004 0.0035 Temps d’execution 0.003 0.0025 0.002 0.0015 0.001 0.0005 0 0 100000 200000 300000 400000 500000 600000 700000 800000 900000 N 1e+06 25.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Insertion dans la chaine de compilation Pythran dispose d'une phase d'optimisation qui travaille sur l'AST du programme Python avant la conversion en C++. Réduction des expressions constantes. Transformation des List Comprehension en combinaison de fonctions. Transformation des Generator Expressions en combinaison de générateurs itertools. 26.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Optimisations à réaliser range -> xrange Fonction -> Équivalent itertools List Comprehensions -> Generator Expressions 27.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Transformation des List Comprehension Transformation triviale : remplacer un noeud ast.GeneratorExpression. ast.ListComp par un 28.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Transformation des fonctions Transformation moins triviale def r a n g e ( n ) : foo = zip r e t u r n map ( lambda x , y : x ∗ y , f o o ( r a n g e ( n ) , r a n g e ( n ) ) ) def b a r ( n ) : r e t u r n sum ( r a n g e ( n ) ) 29.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Pythran Détection des allocations temporaires inutiles Application Application à Pythran Résultats Conclusion Cas particuliers sum(map(lambda (x,y) : x+y, zip(range(n), range(n)))) 0.018 With optimization Without optimization 0.016 0.014 0.012 time 0.01 0.008 0.006 0.004 0.002 0 0 100000 200000 300000 400000 500000 600000 700000 800000 900000 n 30.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Cas moyen Problème : Combien y a-t'il d'allocations temporaires inutiles dans un programme moyen ? 31.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Pythran Application Résultats Cas moyen Problème : Combien y a-t'il d'allocations temporaires inutiles dans un programme moyen ? Susamment pour justier les choix de Python 3. 31.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Plan de la présentation 1 Contexte Les générateurs de Python Le module itertools pour Python 2.X Le cas Python 3 2 Détection des allocations temporaires inutiles Objectif Annotation de l'AST Analyse interprocédurale Résumé 3 Application à Pythran Pythran Application Résultats 4 Conclusion 32.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Conclusion Appliqué à Pythran, la méthode permet des gains de performances signicatifs dans les cas qui s'y prêtent. D'autres applications sont possibles, comme l'amélioration de 2to3, le convertisseur Python 2 vers Python 3. 33.0 Alan Raynaud Élimination d'allocations temporaires en Python Contexte Détection des allocations temporaires inutiles Application à Pythran Conclusion Résumé Contexte En Python l'allocation de mémoire temporaire à un coût en performances, mais il existe des outils pour y remédier. Détection de mémoire temporaire inutile Annotation des noeuds de l'AST où on pourrait utiliser un générateur. Calcul de fonctions de poids pour déterminer si les arguments passés à une fonction peuvent être annotés. Application à Pythran Implémentation de l'algorithme en Python. Transformations éliminant les allocations temporaires inutiles. Alan Raynaud Élimination d'allocations temporaires en Python