Journal Pythran 0.2 : Python peut-il être aussi rapide que du C ?

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
19
17
fév.
2013

Salut petit journal, toi qui est fan de Pythran :-)
Mais oui, tu sais, ce traducteur Python -> C++ pour le prototypage d'algorithmes dans cette merveille d'expressivité et de concision qu'est le Python ! Sinon, je te renvoie à http://pythonhosted.org/pythran/ où tu trouveras un peu de matière à te mettre sous la dent.

Tu as sûrement déjà lu ces deux posts un peu vieux mais assez cocasses :

mais sais tu que Pythran commence à générer du code qui tourne presque aussi vite que du C ?

Allez un petit cadeau, tiré de la branche compas2013 du dépot https://github.com/serge-sans-paille/pythran.git, pas encore intégrée dans master, mais qui présage du très bon.

Le code suivant, qui est un prototype d'algo de géomatique

#pythran export run(float, float, float, float, float, float, float array 2)
import math
from numpy import zeros
def run(xmin, ymin, xmax, ymax, step, range_, t):
    range_x = int((xmax - xmin )/step)
    range_y = int((ymax - ymin )/step)
    print xmax, xmin, range_x
    print ymax, ymin, range_y
    print step
    pt = zeros((range_x, range_y, 3))
    "omp parallel for private(i,j,k,tmp)"
    for i in xrange(range_x):
        for j in xrange(range_y):
            pt[i,j,0], pt[i,j,1] = (xmin+step*i)*180/math.pi, (ymin+step*j)*180/math.pi
            for k in xrange(t.shape[0]):
                tmp = 6368.* math.acos( math.cos(xmin+step*i)*math.cos( t[k,0] ) * math.cos((ymin+step*j)-t[k,1])+  math.sin(xmin+step*i)*math.sin(t[k,0]))
                if tmp < range_:
                    pt[i,j,2]+= t[k,2] / (1+tmp)
    return pt

tourne aussi vite après passage dans pythran que son homologue C. Et ça c'est la grande classe, non ?

Tu auras noté avec tendresse la petite directive OpenMP, qui permet à cet algo de s'exécuter en parallèle :-)

  • # show me the code

    Posté par  . Évalué à 6.

    mais sais tu que Pythran commence à générer du code qui tourne presque aussi vite que du C ?

    mouais… reste plus qu'a le prouver ;-)

    • [^] # Re: show me the code

      Posté par  (site web personnel) . Évalué à 6.

      Homme de peu de foi !

      Test efectué à l'instant avec la branche compas2013 du dépot sus-cité
      Sur l'archive http://ridee.enstb.org/sguelton/hyantes_bench.tgz

      En supposant pythran installé quelque par

      # la ref
      clang -O2 hyantes.c -lm -o hyantes
      time ./hyantes 'Rhone-alpesXYLongLat_pop.txt' 1.1 32 4 35 0.01 40 > /dev/null
      real    0m22.223s
      
      CXX=clang++ pythran -O2 hyantes_core.py
      time python hyantes.py > /dev/null
      real    0m22.767s
      
      # pareil avec gcc
      gcc -O2 hyantes.c -lm -o hyantes
      time ./hyantes 'Rhone-alpesXYLongLat_pop.txt' 1.1 32 4 35 0.01 40 > /dev/null
      real    0m25.905s
      
      CXX=g++ python ~/sources/pythran/scripts/pythran -O2 hyantes_core.py
      time python hyantes.py > /dev/null
      real    0m26.362s
      
      

      Le tout sur un Core I7.

      à vot' service Saint Thomas !

      • [^] # Re: show me the code

        Posté par  . Évalué à 10.

        Merci!

        Un "détail" me saute aux yeux en comparant les sources C et Python. Je suis surpris que tu compares les performances entre un code en python avec OpenMP vs un code en C sans OpenMP.

        Je viens de co la branche compas2013 pour faire des tests, malheureusement je n'arrive pas à lancer pythran sur ma machine, l'erreur semble venir de pythonic++ ou de mon compilateur (gentoo 4.6.3)

        By Jove! Your environment does not seem to provide all what we need
        E: [Errno 65] pythonic++ not found, try to add -I or -L flags?
        ~/pythran/scripts/../pythran/pythonic++/core/utils.h:77:48: désolé, pas implanté: cannot expand ‘Types ...’ into a fixed-length argument list
        
        

        Du coup, en testant uniquement la version C

        AVANT (sans OpenMP)

        gcc -O2 hyantes.c -lm -o hyantes1
        time ./hyantes 'Rhone-alpesXYLongLat_pop.txt' 1.1 32 4 35 0.01 40 > avant
        real    1m13.791s
        user    1m13.753s
        sys     0m0.003s
        
        

        APRES (avec OpenMP)

        <emacs> / <vim> hyantes.c + un coup de #pragma omp parallel
        gcc -O2 hyantes.c -fopenmp -lm -o hyantes2
        time ./hyantes 'Rhone-alpesXYLongLat_pop.txt' 1.1 32 4 35 0.01 40 > apres
        real    0m9.100s
        user    1m43.181s
        sys         0m0.008s
        
        

        N'étant pas une bête avec OpenMP, je préfère vérifier.

        diff avant apres
        echo $?
        0
        
        

        Conclusion un temps d’exécution divisé par 8 (CPU i7-3930K).

        Je n'ai pas pu comparer avec pythran, mais j'ai comme l'impression que :
        - pythran avec OpenMP est aussi rapide que le code en C sans OpenMP
        - le code en C avec OpenMP est 8x plus rapide que pythran avec OpenMP.

        • [^] # Re: show me the code

          Posté par  (site web personnel) . Évalué à 6.

          Je suis surpris que tu compares les performances entre un code en python avec OpenMP vs un code en C sans OpenMP.

          Mais non, la vie n'est pas remplie de personnes malhonnêtes. Pour prendre en compte les directives OpenMP dans pythran, il faut spécifier -fopenmp, tout comme gcc. Pour l'exemple du dessus, elles sont bêtement ignorées…

          Pour ton problème de compil, ça semble lié à un problème de support du C++11. Quelle est la version de ton compilo ?

          Ici:
          Debian clang version 3.1-8
          gcc (Debian 4.7.2-5) 4.7.2

          En tout cas merci de pousser si loin la comparaison :-)
          La suite au prochain épisode (si tu passes sur FreeNode #pythran, je me ferai un plaisir de discuter :-))

  • # Je ne comprend pas trop…

    Posté par  . Évalué à 9.

    En fait, ça permet de faire tourner un langage au système de type mou et dynamique aussi rapidement qu'un langage fortement et statiquement typé, à condition que le code du premier langage respecte les contraintes sur les types qu'impose le second ?

    Please do not feed the trolls

    • [^] # Re: Je ne comprend pas trop…

      Posté par  (site web personnel) . Évalué à 3.

      Oui c'est ça ! Si le code est implicitement non polymorphe, on s'en sort pas trop mal. Sinon on crache une erreur c++ de 50 lignes de long :-)

      • [^] # Re: Je ne comprend pas trop…

        Posté par  . Évalué à 3. Dernière modification le 18 février 2013 à 15:14.

        Et donc comment est-ce que ça se positionne par rapport à Cython ?

        EDIT: pardon, j'avais pas encore lu ce que tu en dis plus bas.

  • # UUUUUrgh !!!!!!

    Posté par  . Évalué à 4.

    ce traducteur Python -> C++ pour le prototypage d'algorithmes dans cette merveille d'expressivité et de concision qu'est le Python

    Mettre python et concision dans la même phrase, c'est vraiment se moquer du monde. Concision et explicite ne vont pas bien ensemble.

    Si on veut parler de concision, parlns Perl, là je serai d'accord.

    • [^] # Re: UUUUUrgh !!!!!!

      Posté par  . Évalué à 10.

      bof, en une ligne de python, tu as besoin de 100 lignes C, donc la concision pour python, moi j'y crois.

      • [^] # Commentaire supprimé

        Posté par  . Évalué à 10.

        Ce commentaire a été supprimé par l’équipe de modération.

        • [^] # Re: UUUUUrgh !!!!!!

          Posté par  (site web personnel) . Évalué à 10.

          Et tu es bien content que d'autres réfléchissent à ta place sur une façon d'exécuter de manière décente ta ligne. Normal. Si tu veux la perf de la perf, faut aller la chercher et se retrousser les manches, sinon, tu es content que d'autres capitalisent leur savoir faire dans un outil.

  • # Commentaire supprimé

    Posté par  . Évalué à 4.

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: Je reste plus que dubitatif

      Posté par  (site web personnel) . Évalué à 5.

      C'est vrai que je ne me suis pas fendu d'un long commentaire sur les raisons de ces résultats… disons que cela alimente le débat… choquer pour provoquer la discussion :-)

      Les tableaux utilisés dans le code Python sont des tableaux NumPy, et pas des listes de listes. Ces tableaux ne sont ni plus ni moins que des tableaux natifs encapsulés. Les accès se font en row major en C et en Python et le code donné en tient bien sûr compte.

      Autrement dit : très peu de défauts de cache dans cet exemple, que ce soit pour le code C (cf. http://ridee.enstb.org/sguelton/hyantes_bench.tgz) ou le code Python, ou le code C++ généré d'ailleurs.

      Pour en savoir plus: The NumPy array: a structure for efficient numerical computation

      • [^] # Commentaire supprimé

        Posté par  . Évalué à 6. Dernière modification le 18 février 2013 à 13:15.

        Ce commentaire a été supprimé par l’équipe de modération.

        • [^] # Re: Je reste plus que dubitatif

          Posté par  (site web personnel) . Évalué à 1.

          Très joli.

          Je suis bien d'accord avec toi, il y a pleins de possibilités d'optimisations :-) Et après tes transfos, pas mal d'opportunités de vectorisation apparaissent. On s'éloigne cependant pas mal du prototype original, non ?

          Le gars qui fait de la géomatique, il a pas le temps de faire le (bon) travail d'optimisation que tu as fait. Pas sûr qu'il en soit capable d'ailleurs.

          Dis autrement, je préfère être celui qui maintient la version Python que la version C, et celui qui maintient la version C que la version C optimisée.

          Le challenge est d'écrire l'algo le plus proche de sa description, et de voir ce qu'un compilo peut en tirer. D'ailleurs rien ne m'empêche (au moins pour la mémoization des appels à cos/sin) d'écrire la même variante en Python.

          Ce qui confirme qu'un code évolue (comme les Pokemons !)
          1. Python
          2. C
          3. C optimisé
          4. vectorisation, parallélisation, et pourquoi pas GPUs et autres

          Avec un SLOC qui augmente à chaque étape d'ailleurs.

          Ton code montre que gcc a du mal à faire 1 -> 2 (ou 3 d'ailleurs)
          J'essaie quant à moi de faire 0 -> 2.

          • [^] # Commentaire supprimé

            Posté par  . Évalué à 6.

            Ce commentaire a été supprimé par l’équipe de modération.

  • # World is full of nonsense.

    Posté par  . Évalué à 10. Dernière modification le 17 février 2013 à 22:57.

    Tiens, si on créait un langage typé par valeurs, interprété, pour simplfier le mode de développement ? Parce que la compilation, c'est atroce, c'est trop compliqué.

    15ans plus tard. Oh. C'est étrange. En fait, les types et la compilation, ça sert énormement ! Ça permet d'optimiser le code et d'avoir des performances décentes, ça permet de garantir pleins de propriétés et réduit le nombre de bugs dans le code final. Mince alors !

    Bon. C'est pas grave. Puisque les gens veulent des perfs, on va compiler vers un des langages les moins fiables (mais avec des perfs potables), et ça sera réglé. Et tant qu'a y être, on va écrire un compilateur à la volée.

    20ans plus tard. Bon. A la fin, on se retrouve avec un truc 20x plus compliqué et plus complexe à coder qu'un simple compilateur, sans avoir tout les avantages de la compilation. En plus, on a plusieurs implémentations avec des perfs tellement différentes qu'une personne écrivant du code ne sait pas du tout sur quoi il tournera potentiellement.

    Bref, c'est le bordel.

    • [^] # Re: World is full of nonsense.

      Posté par  (site web personnel) . Évalué à 7.

      Et quel plaisir de participer au foutoir ambiant :-)

      • [^] # Re: World is full of nonsense.

        Posté par  . Évalué à 6.

        Note que je ne critique pas pythran en soi, je conçoit totalement que vu la code base et les produits qui existent en python, il est désormais profitable d'avoir ce genre d'outils pour certains usages, je dis juste que sur le long terme, même si les langages dynamiquement typés ont du succés, ils ne sont pas forcément la voie la plus simple et la plus performante à suivre.

    • [^] # Re: World is full of nonsense.

      Posté par  . Évalué à 3. Dernière modification le 19 février 2013 à 17:44.

      Tu l'explique tellement bien que je vois pas où est le bordel.
      On simplifie le dev et on accélère les parties qui en ont vraiment besoin.

      J'ai jamais vraiment compris ceux qui veulent absolument tout faire en C.
      Si ils refusent les progrès apportés par des langages de plus haut niveau d'abstraction, pourquoi ne pas s'être arrêté à l'assembleur. Le C est déjà une abstraction.

      C'est un peu comme les Amish qui se sont arrêté en 1800. Pourquoi pas en 1200 ou en -3000.

      Note que je te vise pas particulièrement, c'est une remarque générale.

      • [^] # Re: World is full of nonsense.

        Posté par  (site web personnel) . Évalué à 3.

        Si ils refusent les progrès apportés par des langages de plus haut niveau d'abstraction, pourquoi ne pas s'être arrêté à l'assembleur. Le C est déjà une abstraction.

        L'assembleur aussi.

      • [^] # Re: World is full of nonsense.

        Posté par  (site web personnel) . Évalué à 2.

        Y'a des langages modernes, typées fortement (avec inférence de type) et compilés aussi tu sais.

      • [^] # Re: World is full of nonsense.

        Posté par  . Évalué à 2.

        Je parlais pas de C, mais de langages comme ML (haskell, ocaml, etc), ou même le prometteur rust. Ou scala sur la JVM, ou même dans une moindre mesure, go.

        Python n'est pas LE progrès. C'est une manière de l'envisager.

  • # Ça m'intéresse

    Posté par  . Évalué à 5.

    Salut, moi j'ai justement un code python pour faire du calcul scientifique qui pourrait bénéficier de cette approche. En fait, coder en python est plus rapide que coder en C, mais le temps d'exécution est plus long, ce qui peut ne pas être un inconvénient rédhibitoire si on est patient. Par contre, le fait de potentiellement pouvoir atteindre la vitesse du C c'est très bien, car ça permet de donner un ordre de grandeur du temps mis pour faire le calcul si le code était directement traduit en code machine.

    Mais quand même, j'ai un peu l'impression que ce serait trop beau pour être vrai. Comment ce pythran va-t-il s'en sortir devant un code plus complexe, utilisant des fonctionnalités particulières dans des modules spéciaux etc ? Parce que le code en exemple, tu peux le faire en C ça va te prendre 2× plus de lignes mais au moins c'est portable et ça va compiler une fois pour toutes. Donc si c'est juste pour économiser 30 lignes de code (principalement des déclarations, des accolades et des définitions un peu verbeuses), est-ce que ça ne vaut pas le coup de le faire en C directement ?

    Systemd, the bright side of linux, toward a better user experience and on the road to massive adoption of linux for the desktop.

    • [^] # Re: Ça m'intéresse

      Posté par  . Évalué à 3.

      Je pense que Pythran est surtout utile pour Python => C++.
      Pour le C, tu as Cython. Tu peux compiler ton code python tel quel, ou l'optimiser en utilisant la syntaxe de Cython (qui reste très proche de Python, et donc rapide à écrire), c'est vraiment pas mal pour les perfs, surtout quand tu ne connais pas vraiment le C.
      J'en avais eu besoin il n'y a pas si longtemps, où j'avais une fonction qui travaillait sur une palette de couleurs d'une image (y avait plusieurs opérations consécutives). En python, à cause de la boucle et surtout, à cause des appels de fonctions à l'intérieur de celle-ci (même en optimisant un max, en plaçant les fonction dans des variables locale avant les appels, en utilisant les générateurs et en utilisant les structures comme array ou numpy), il continuait à y avoir un temps de latence ~ une seconde dans l'interface utilisateur, ce que je considère comme chiant pour du rendu en temps réel.
      Après optimisation dans Cython, ça allait bien mieux, l'opération était imperceptible à l’œil nu.

      En utilisant une bibliothèque Python d'image, je n'aurais certainement pas eu besoin de cette opération, mais c'était un choix de ma part, ne voulant pas ajouter une dépendance supplémentaire pour une opération facultative et mineure dans le logiciel. Et puis, je voulais faire mumuse avec Cython au moins une fois.

      • [^] # Re: Ça m'intéresse

        Posté par  (site web personnel) . Évalué à 2.

        Boarf C ou C++, c'est pas le problème, dans les deux cas ça se traduit en code natif. C'est assez transparent pour l'utilisateur lambda.

        En ce qui concerne Cython, Je suis assez de l'avis de l'auteur de Nuitka qui dit que cython ça casse la compatibilité avec le code d'origine et c'est pô bien. Pythran n'a pas ce problème.

        Bon par contre cython supporte beaucoup plus de modules que nous hein, pythran c'est pas du dix ans d'âge non plus, plutôt moins d'un an sur les week end.

        • [^] # Re: Ça m'intéresse

          Posté par  . Évalué à 4.

          Oups, je n'avais pas bien lu le journal, venant de me réveiller. C'est de la syntaxe pure-python. Je ne sais pas pourquoi, mais j'avais en tête un code en C, mélangé à du python (j'ai du confondre avec un autre post plus haut).
          Et je ne comprenais pas pourquoi tu parlais de compatibilité, ayant ce code C en tête.

          Pour celles et ceux n'ayant jamais vu un code Cython, voilà ce que ça donne sur une petite fonction (et pourquoi ça casse justement la compatibilité):

          cpdef change_palette_hue(palette, int hue):
              cdef unsigned long color, color2
              cdef int a, r, g, b, index
              cdef float h, s, v, hh
              hh = hue/360.0
          
              for index, color in enumerate(palette):
                  a = (color >> 24) & 0xff
                  r = (color >> 16) & 0xff
                  g = (color >> 8 ) & 0xff
                  b = (color >> 0 ) & 0xff
                  h, s, v = rgb_to_hsvNEW(r, g, b)
                  r, g, b = hsv_to_rgbNEW(hh, s, v)
                  color2 = (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | b & 0xff
                  palette[index] = color2
          
              return palette
          
          

          Et par conséquent, à voir ton code plus haut, ça donne bien plus envie que ce que j'imaginais ce matin…

    • [^] # Re: Ça m'intéresse

      Posté par  (site web personnel) . Évalué à 2.

      Salut,
      ton code m'intéresse. On est en travailler sur le support NumPy (c'est pour ça que c'est dans une branche…), et ton appli peut nous servir de base. Si tu peux le mettre en ligne quelque part, ou le poster sur la mliste pythran, ce serait chouette (voire ce serait hibou).

      que ce serait trop beau pour être vrai

      Tu as partiellement raison. On supporte quelques modules standards (math, random…) mais pas mal de fonctionnalités du langage (list comprehension, générateurs, …). La plus grosse limitation c'est sûrement l'absence de support pour les classes utilisateurs. là encore si tu rends ton code dispo, on peut ajouter le support pour les fonctionnalités qui manquent.

      • [^] # Re: Ça m'intéresse

        Posté par  . Évalué à 2.

        Merci beaucoup pour la proposition :) Vous êtes très réactifs, c'est cool. Malheureusement, je ne pense pas que je puisse poster mon code pour des raisons indépendantes de ma volonté (c'est de la recherche − non, ce n'est pas particulièrement sensible mais c'est interdit dans mon contrat − et c'est propriété de mon employeur).

        En fait dans l'ensemble, à part quelques modules un peu exotiques (sys, re, time) dont on peut se passer, le code ne fonctionne qu'à partir de modules de mathématiques (random justement, et scipy.special, scipy.interpolate, scipy.optimize), tous modules très pratiques et beaucoup plus simples à utiliser en python qu'en C ou en C++.

        Je te ferai peut être un rapport…

        Systemd, the bright side of linux, toward a better user experience and on the road to massive adoption of linux for the desktop.

    • [^] # Re: Ça m'intéresse

      Posté par  (site web personnel) . Évalué à 2.

      le fait de potentiellement pouvoir atteindre la vitesse du C

      Je trouve quand même bizarre ce raccourcis entre vitesse d’exécution d’un binaire obtenu après compilation depuis un langage, et vitesse d’un langage.

      Je ne vois pas ce qui empêcherait de compiler depuis n’importe quel langage vers un binaire optimisé. Bien sûr l’optimisation avec garantie de conformité des résultats est un sujet qui est loin d’être trivial. Et bien sûr dans des langages proches de l’architecture machine comme le C on peut formuler directement des expressions dont la compilation donnera un binaire (proche de l’)optimal. En gardant ces idées en tête, quel serait le problème théorique fondamentalement insurmontable empêchant de générer un binaire optimal depuis un langage quelconque ?

      • [^] # Re: Ça m'intéresse

        Posté par  . Évalué à 2. Dernière modification le 18 février 2013 à 13:51.

        Problème de type essentiellement. Il me semble que les seuls langages qui à ma connaissance ont une vitesse d'exécution proche du C sont des langages à typage statique, par exemple C++, ocaml, etc.

        Le fait d'écrire un algo en C fait que également, on va s'orienter vers les types les plus adaptés et faire en sorte que le programme soit optimisé avec les outils à disposition.

        Sinon dans l'absolu ça doit être possible d'optimiser n'importe quel langage pour peu que le compilateur soit suffisamment performant, mais il me semble que ça devra être un compilateur ultra-performant.

        J'ai comme l'impression qu'il y a un problème d'œuf et de poule quelque part, mais je ne suis pas du tout un spécialiste des langages.

        Systemd, the bright side of linux, toward a better user experience and on the road to massive adoption of linux for the desktop.

      • [^] # Re: Ça m'intéresse

        Posté par  (site web personnel) . Évalué à 3.

        Pour faire de n'importe quoi un binaire optimisé, il faut que tu puisses déduire les types exactes de chaque valeur. Cela nécessite une analyse global du programme qui n'est pas toujours possible.

        Par exemple, en C, si tu as une fonction qui prend 2 pointeurs de même type en entrée, sans "restrict", le compilo part du principe que les 2 zones pointées peuvent se recouvrir. C'est idiot pour 99% des cas, mais cela oblige des passages vers la mémoire totalement inutile.

        En C, 99% du temps tu te fous de l'ordre des éléments dans la déclaration de structure, faire un tri pour éviter le padding serait plus efficace, mais tu change l'ordre prévus par le codeur, ce qui peut poser problème (tableau de taille nul en fin de structure par exemple).

        Quand tu manipules des données flottantes IEEE754, aucune transformation ne peut se faire sans perte, car l'ensemble des nombres n'est pas un ensemble mathématique classique. Sans information sur les "pertes acceptables de précision" , le compilo ne fait rien ou presque.

        Toutes ses informations peuvent se retrouver par une analyse précise et total du code, mais cela devient hyper complexe.

        "La première sécurité est la liberté"

  • # Liaison dynamique

    Posté par  (site web personnel) . Évalué à 1.

    Question : comment compiles-tu la liaison dynamique ? (ie. l'appel à méthode de classe lorsque tu as plusieurs type receveur possible)

    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

    • [^] # Re: Liaison dynamique

      Posté par  (site web personnel) . Évalué à 2.

      Comme dis plus haut, pas de classes utilisateur pour le moment…
      L'objectif numéro 1 c'est d'avoir les perfs du C pour des applis scientifiques, donc on a pas forcément besoin de classes utilisateur. Après, tu peux compiler la partie calcul intensif en pythran et garder le reste en Python, c'est là l'intérêt : seule la partie gourmande en calcul a besoin d'être traduite.

      • [^] # Re: Liaison dynamique

        Posté par  (site web personnel) . Évalué à 1.

        Je lisais ce midi la partie Fr de ta thèse, tu utilises des techniques que tu y as développés dans Pytran ? Tu comptes faire de la génération pour GPU ?

        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

        • [^] # Re: Liaison dynamique

          Posté par  (site web personnel) . Évalué à 3.

          Wooo, un lecteur de ma thèse. Si on m'avait dis que cela arriverait un jour :-)

          Niveau optimisations, ce sera d'abord les instructions vectorielles qui vont y passer, et la fusion d'opérateur. Quand on regarde du code numpy, c'est trop tentant !

          Et puis l'analyse de préconditions aussi…

          Les GPUs c'est pas pour tout de suite non. regarde du côté de copperhead si tu es pressé.

          J'essaie de faire attention à la conception du compilo aussi, pour rendre l'injection de passes facile :-)

          • [^] # Re: Liaison dynamique

            Posté par  (site web personnel) . Évalué à 1.

            Elle est très intéressante cette thèse, alors même qu'au début, j'avais pas compris et je me demandais si c'était pas plus un truc d'ingénierie qu'autre chose ;-)

            Pour le peu que j'ai vu de copperhead, tu dois te plier à la sémantique du GPU. Trop brainfuck pour moi et pour la plupart de gens.

            Je pense que le genre d'outil que tu as développé va devenir très utile, parce à chaque fois on développe un langage pour le GPU, le chose, etc…
            Or, leur sémantique est beaucoup trop particulière.
            Et avec la généralisation du multicoeur et l'incapacité tant des devs que des compilateurs à être intelligents, il va falloir faire de la transformation de code.
            L'idéal serait évidemment que cet outil de conversion soit prouvé en Coq ou quelques chose de ce genre.

            « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

            • [^] # Re: Liaison dynamique

              Posté par  (site web personnel) . Évalué à 1.

              Déjà si les types incluaient range et précision absolu, on pourrait faire des transformations avec "perte maitrisée" de la précision de calcul. Là avec le code IEEE754, on ne peut rien en faire de "maitrisable".

              J'imagine que générer du code openMP, et du gcc vectorisable par gcc ne doit pas être sorcier, à condition de maitriser le layout mémoire des données.

              "La première sécurité est la liberté"

              • [^] # Commentaire supprimé

                Posté par  . Évalué à 2.

                Ce commentaire a été supprimé par l’équipe de modération.

                • [^] # Re: Liaison dynamique

                  Posté par  (site web personnel) . Évalué à 1.

                  Une relative est plus raisonnable…

                  En fait, non. Si tu prends une précision relative, que faire autour de zéro et que faire des nombres dénormalisés ? Il va te falloir en plus une précision absolue juste pour ce cas-là.

                  De plus, si tu regardes des spécifications, les grandeurs d'entrée ou de sorties de calcul sont toujours en absolue : précisions d'ADC, précision de capteur, "lsb" de nombre entier pour la musique, pixel pour des images, etc…
                  Dans le cas de comptabilité, on a envie d'avoir une erreur inférieur au centime, quelque soit les sommes intermédiaires.

                  Les nombres flottants peuvent être utilisés avec une précision absolue si tu as le range, donc, c'est bon.

                  "La première sécurité est la liberté"

                  • [^] # Commentaire supprimé

                    Posté par  . Évalué à 2. Dernière modification le 20 février 2013 à 16:00.

                    Ce commentaire a été supprimé par l’équipe de modération.

                    • [^] # Re: Liaison dynamique

                      Posté par  (site web personnel) . Évalué à 2.

                      Quand tu fais un logiciel, du point de vue système tu te fou de savoir si tu utilises des flottants ou des virgules fixes. Il s'agit toujours de "nombre". En compta, il utilise un big number ou équivalent. Un nombre avec range + précision peut être mappé sur n'importe quelle représentation informatique.

                      Un float c'est Significant digits × baseexponent. Donc la précision varie en fonction de ces 3 paramètres. Le range ne donne rien de ces trois paramètres (y a pas que le IEEE dans la vie).

                      Sauf qu'il y a très peu de variantes pour ses 3 variables. Si ta fpu n'est pas IEEE754, je ne vois pas ce que tu peux faire au niveau précision car tu ne sais même pas ce que la fpu va te perdre.

                      Si tu veux de l'absolu, tu utilise le point fixe. Les flottants donnent toujours une précision variable quelque soit l'intervalle choisi (Il y a évidement une précision minimale - ensemble fini d'éléments donc différences 2 à 2 finies).

                      Oui, mais on veut une précision minimum, pas une précision fixe. On veut une précision finale du point de vue système, on se contre fou de la manière d'y arriver.

                      "La première sécurité est la liberté"

                      • [^] # Re: Liaison dynamique

                        Posté par  . Évalué à 3.

                        http://en.wikipedia.org/wiki/Interval_arithmetic Tu veux implémenter du calcul par intervalle ?

                        • [^] # Re: Liaison dynamique

                          Posté par  (site web personnel) . Évalué à 1. Dernière modification le 20 février 2013 à 17:28.

                          Non, je veux un type de donné qui correspond aux problèmes systèmes, c'est ensuite au compilateur de faire son boulot pour trouver la meilleur représentation machine et de faire des simplications mathématique qui rende le code plus simple. On peut imaginer des factorisations pour réduire le nombre de division et l'inverse pour augmenter le parallélisme du code. On peut encore imaginer aller plus loin avec une linéarisation des équations valides dans le range précisé et la précision voulue.

                          Tout cela n'est possible qu'avec range et précision absolu (ou absolu + relatif même si c'est plus chiant) et que l'on considère les équations comme avec des réels et non comme avec des nombres flottants.

                          math.acos( math.cos(xmin+step*i)*math.cos( t[k,0] ) pour une précision donnée se réduit à un polynôme ou presque.

                          "La première sécurité est la liberté"

                          • [^] # Re: Liaison dynamique

                            Posté par  . Évalué à 3.

                            C'est quoi un problème système ?

                            • [^] # Re: Liaison dynamique

                              Posté par  (site web personnel) . Évalué à 1.

                              C'est le truc à résoudre avant de commencer à coder.

                              "La première sécurité est la liberté"

                              • [^] # Re: Liaison dynamique

                                Posté par  . Évalué à 2.

                                mmm j'aurai plutôt dit "un problème métier" dans ce cas non ? Un problème système j'aurai plutôt associé ça comme ça au côté purement informatique implémentatoire (compilo / système d'exploitation / FPA …)

                          • [^] # Commentaire supprimé

                            Posté par  . Évalué à 2.

                            Ce commentaire a été supprimé par l’équipe de modération.

                            • [^] # Re: Liaison dynamique

                              Posté par  . Évalué à 3.

                              Il faut qu'il fasse de l'Interprétatation abstraite combiné avec de la programmation par contrainte sur les intervalle.

                              • [^] # Commentaire supprimé

                                Posté par  . Évalué à 2.

                                Ce commentaire a été supprimé par l’équipe de modération.

                                • [^] # Re: Liaison dynamique

                                  Posté par  . Évalué à 3.

                                  En l'occurence ce serait juste pour le compilateur pour savoir si il a le droit ou pas de faire certaines optims, c'est pas forcément très grave, et puis il y a moyen que ça soit très rapide sur un calcul standard.

                                  • [^] # Re: Liaison dynamique

                                    Posté par  (site web personnel) . Évalué à 1.

                                    Exactement. Il y a des tas d'optimisation simple à faire pour augmenter la vitesse d'un code numérique qui sont très dure à faire si on ne connait pas les besoins réels du codeur concernant la précision requise.

                                    On peut même imaginer une implémentation sans code flottant, et sans devoir faire totalement la conversion à la main.

                                    Le gros hic, c'est la stabilité numérique :/ Et ça, je vois très mal un compilo être capable de l'estimer.

                                    Tu parles des équations bizarres qui peuvent diverger autour de points spéciaux ? Parce que dans l'embarqué, qui utilise des code rétroactif, il utilise en général des équations qui évitent d'être sensible aux bits de poids faible d'une grandeur, car elles sont physiques et donc soumises elle-même à une erreur de mesure. Les équations instables sont évitées comme la peste : comment prouver que le système ne peut par partir en sucette ? Si il y a des hommes dedans, cela peut être gênant.

                                    "La première sécurité est la liberté"

                                    • [^] # Commentaire supprimé

                                      Posté par  . Évalué à 2. Dernière modification le 21 février 2013 à 11:26.

                                      Ce commentaire a été supprimé par l’équipe de modération.

                                      • [^] # Re: Liaison dynamique

                                        Posté par  (site web personnel) . Évalué à 1. Dernière modification le 21 février 2013 à 12:33.

                                        Concernant la stabilité, c'est par exemple la répétition de x= x(-1)*.1 ? A part dans le monde des calculs scientifiques, ce genre de chose est évité dans le traitement du signal, parce ce que les valeurs d'entrés ne sont de toute façon jamais connu de façon précise.

                                        Je veux dire par là, qu'il existe toute une gamme d'équation non simplifiable du style de celle que tu décris, mais elles ne sont pas tant utilisé tant que ça dans les faits.

                                        Connaître la précision requise des opérations de base (+,-,*,/) c'est bien beau mais ce qui compte réellement c'est la précision globale de l'algo.

                                        Oui mais en partant des erreurs connu de "+" (0.5 lsb) tu peux en déduire la propagation d'erreur dans une équation et la borner d'une façon ou d'une autre, dans l'implémentation choisi par le compilo. Genre ((a+b)*c+de)+a pourrait être traduit en (ac+bd)+(de+a) si on peut supporter la perte de 2 ou 3 lsb dans le résultat attendu.

                                        Mais si tu connais une solution, je suis preneur et la communauté scientifique aussi. Je crois même qu'il est probable que tu recevras une récompense pour ça…

                                        Sacré motivation :) Je pensais simplement à simplifier des équation mathématique, genre un -fast-math avec résultat contrôlé. En voulant faire ça, je me suis rendu compte que l'on ne pouvait rien faire avec du code C ou C++ utilisant des flottants : il manque trop d'information.

                                        L'idée ressemble beaucoup au ROM (reduce order modeling) dont j'ai entendu parlé récemment, le compilo travaillerai au niveau equation et non plus au niveau model 3D.
                                        http://www.bris.ac.uk/aerodynamics-research/roms/

                                        "La première sécurité est la liberté"

                                        • [^] # Commentaire supprimé

                                          Posté par  . Évalué à 2.

                                          Ce commentaire a été supprimé par l’équipe de modération.

                                          • [^] # Re: Liaison dynamique

                                            Posté par  (site web personnel) . Évalué à 1.

                                            Le point 2 parle surtout des problèmes de mantisses quand on additionne 2 nombres de tailles différentes. C'est bien une forme d'accumulation d'erreur. C'est le "fameux" problème d'addition des souris et des éléphants. Ici, la souris passe sous le lsb dans l'addition avec l'éléphant.

                                            Pour illustrer son point 4, il utilise chop comme fonction d'arrondit. IEEE754 utilise round to even, c'est pas pour rien. En moyenne, cet arrondi annule les effets cumulatifs. Et il parle de problème très particuliers.

                                            Je suis bien conscient que le cas général ne peut pas être géré facilement, mais les cas particuliers utiles pourraient l'être.

                                            "La première sécurité est la liberté"

            • [^] # Re: Liaison dynamique

              Posté par  (site web personnel) . Évalué à 1.

              Elle est très intéressante cette thèse,

              Owi, continue à envoyer des fleurs comme ça, l'ego aime :-)

              Pour le peu que j'ai vu de copperhead, tu dois te plier à la sémantique du GPU. Trop brainfuck pour moi et pour la plupart de gens.

              Je suis d'accord.

              L'idéal serait évidemment que cet outil de conversion soit prouvé en Coq ou quelques chose de ce genre.
              Je n'ai qu'une vie, qui est déjà bien remplie :-)

  • # Et par rapport a du pur Python ?

    Posté par  . Évalué à 3.

    Et qu'en est-il du gain de vitesse de Pythran par rapport a du pur numpy (codé correctement). L'exemple donné reviens à:

    def run(xmin, xmax, ymin, ymax, step, range_, t):
        X,Y = meshgrid(linspace(xmin,xmax,step),linspace(ymin,ymax,step))
        pt = zeros((step,step,3))
        pt[:,:,0] = X*180/pi
        pt[:,:,1] = Y*180/pi
        for k in range(t.shape[0]):
            tmp = 6368.*arccos(cos(X)*cos(t[k,0])*cos(Y-t[k,1])+sin(X)*sin(t[k,1]))
            pt[:,:,2] += where(tmp < range_, t[k,2]/(1+tmp), 0)
        return pt
    
    

    Je n'ai pas Pythran pour comparer. Quel gain peut-on en attendre?

    A noter que cet exemple a été écrit vite-fait, il y a probablement moyen d'optimiser en faisant sauter la boucle sur k.

    • [^] # Re: Et par rapport a du pur Python ?

      Posté par  (site web personnel) . Évalué à 2.

      Yes, ça c'est du code comme on aime.

      Dès que pythran supporte les deux-trois fonctions numpy qui manquent, je te réponds :-)
      Mais c'est clairement la marche à suivre !

      (comme je manque un peu de temps actuellement, ça risque de pas être implémenté tout de suite. Un moyen de te tenir au courant ?)

      • [^] # Re: Et par rapport a du pur Python ?

        Posté par  . Évalué à 7.

        (comme je manque un peu de temps actuellement, ça risque de pas être implémenté tout de suite. Un moyen de te tenir au courant ?)

        Un journal linuxfr (moi aussi ça m’intéresse).

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: Et par rapport a du pur Python ?

        Posté par  . Évalué à 1.

        Personnellement, j'ai une approche assez pragmatique pour mon code: se concentrer sur du numpy propre permet en général d'avoir rapidement quelque chose de satisfaisant; quand ça bloque, j'écris en C les fonctions qui en ont besoin. Écrire de petits modules en C n'est pas forcément compliqué, mais c'est chiant (surtout pour gérer correctement les échanges entre Python et C). Je suis donc de loin ce qui se passe sur Pythran, si ça peut permettre de faciliter l'écriture de modules optimisés.

        Donc ma question ici était surtout de savoir si la fonction Pythran (telle que donnée dans le journal) permet un gain notable par rapport au Python (tel que je l'ai écrit). Le tout est de savoir si la perte de lisibilité (on doit expliciter les boucles) est compensé par un gain en efficacité de calcul (travailler directement au niveau des arrays Numpy est déjà très optimisé).

        • [^] # Re: Et par rapport a du pur Python ?

          Posté par  (site web personnel) . Évalué à 3.

          J'ai la même approche par rapport à numpy. 95% du temps, j'arrive à avoir des performances très honorables en utilisant intelligement numpy.
          Par contre, parfois, refactoriser pour gagner des perfs grâce à numpy peut sérieusement nuire à la lisibilité du code (si on mélange index tricks, tensordot, einsum et des reshape, ça devient vite incompréhensible), auquel cas j'écris en C++. C'est souvent lorsqu'il y a plusieurs boucles for imbriquées et qu'elles sont difficiles à traduire en numpy. Du coup, pythran me semble intéressant pour ces cas-là si on arrive à avoir des perfs de boucle for proches du C.

        • [^] # Re: Et par rapport a du pur Python ?

          Posté par  . Évalué à 3.

          Écrire de petits modules en C n'est pas forcément compliqué, mais c'est chiant (surtout pour gérer correctement les échanges entre Python et C).

          Pour moi c'est là que cython est vraiment utile. Ca permet d'écrire rapidement de genre de petits modules sana avoir à gérer les échanges entre python/numpy et C (uniquement déclarer les types des variables).

  • # SMP

    Posté par  . Évalué à 1.

    Et python sur du multicoeur (qui aujourd'hui n'as pas un CPU non multicoeur), comment ça se passe?

    Troll du vendredi…

    http://www.dabeaz.com/python/GIL.pdf

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.