Journal Pythran 0.8.5 - de l'intérêt des compilateurs

Posté par (page perso) . Licence CC by-sa
Tags :
35
24
avr.
2018

Demat' Nal

Pythran, compilateur pour un sous ensemble du langage Python dédié au calcul scientifique, en est à sa version 0.8.5.

En guise d'exemple, il permet de transformer un code source comme celui là :

#pythran export weights(uint8[:,:])
#runas import numpy as np; x = np.arange(10, dtype=np.uint8).reshape(5,2); weights(x)

import numpy as np
def weights(input_data, threshold=0.3):
    n_seq, length = input_data.shape
    weights = np.zeros(n_seq, dtype=np.float32)

    for i in range(n_seq):
        vector = input_data[i, None, :]
        count_matches = np.sum(vector == input_data, axis=1)
        over_threshold = count_matches > (threshold * length)
        total = np.sum(over_threshold)
        weights[i] = 1 / total

    return weights

En un module natif, qui ne fait plus d'appel au Runtime Python si ce n'est aux frontières (allez, petit placement de produit à ce sujet )

Je ne vais pas étaler ici la liste des changements, ce serait redondant avec le Changelog. Il n'est pas encore disponible dans les bonnes librairies (mais pas chez les mauvaises non plus !), mais à défaut vous pouvez vous rabattre sur :

Après ce petit volet publicitaire, un peu de contenu plus intéressant. Déjà c'est la première version où je reçois autant de contribution extérieures. Un gros Merci à Jean Laroche, Pierre Augier et Yann Diorcet pour leurs contributions ! Pas mal de retours de bugs aussi, ce qui prouve l'existence d'utilisateurs :-)

Et pour se raccrocher au titre, sans aucun effort pour l'utilisateur, un code complexe comme grayscott s'exécute maintenant 15% plus rapidement que quand il était compilé avec la version 0.8.4 de Pythran. Ça me permet de conclure ce journal sur une notre très enthousiasmante pour les utilisateurs : parfois, il suffit d'exprimer son code sans penser aux optimisations, et avec le temps le compilateur le rendra meilleur.

Pythran, un compilateur de garde!

  • # la vitesse d'exécution n'est pas le principal intérêt d'un compilateur à mes yeux.

    Posté par . Évalué à 6 (+6/-2).

    Pour moi, le compilo, c'est surtout un outil d'analyse statique.
    Un code compilé, avec tous les warnings activés et considérés comme des erreurs, garantit l'absence de nombreux bugs, je pense notamment aux problèmes de transtypage (-1 == 0xFFFF? Vraiment? Ça dépends.), au bug d'indentation, au code qui n'est pas atteignable, aux variables jamais utilisées alors qu'elles le devraient, aux conflits de noms (ah, ma méthode bar de la classe hello à une variable foo, alors que ma classe à également une propriété foo => ça pue les bugs, présents ou à venir), et j'en oublie.

    • [^] # Re: la vitesse d'exécution n'est pas le principal intérêt d'un compilateur à mes yeux.

      Posté par (page perso) . Évalué à 7 (+6/-0).

      Mais pas que, la performance peut être liée au fait que justement grâce à l'analyse statique, le compilateur peut supprimer les méta-informations de type, et dénouer les abstractions (par exemple le Rust est langage qui se veut avoir des "zéro-cost abstractions"). Ce n'est malheureusement possible que si le typage est strict et sans ambiguïté possible: en Python ça ne sera juste jamais possible à cause des possiblités de monkey patching. L'un ne va pas sans l'autre en réalité, le typage et l'analyse statique permettent par la preuve formelle de garantir un code sans bug, et la garantie et la prédictibilité de ce qui va être exécuté permet les optimisations.

    • [^] # Re: la vitesse d'exécution n'est pas le principal intérêt d'un compilateur à mes yeux.

      Posté par . Évalué à 1 (+1/-1).

      Pour moi, le compilo, c'est surtout un outil d'analyse statique.

      Ça c'est la partie analyse statique du compilateur, mais ça n'est qu'une étape de la compilation et ça n'est même pas toujours la plus intéressante.

      Le compilateur qui va passer ton code source en byte code peut être très intéressant en terme d'analyse statique, mais le JIT qui va en faire un code natif n'a d'intérêt que pour la performance de son code généré.

    • [^] # Re: la vitesse d'exécution n'est pas le principal intérêt d'un compilateur à mes yeux.

      Posté par (page perso) . Évalué à 3 (+1/-0).

      Et si les deux étaient intéressant ? Imaginons que la vitesse d’exécution soit une contrainte fonctionnelle critique de ton produit. On peut imaginer préférer un produit faux (i.e.: avec des bugs, des plantages, des imprécisions) mais extrêmement rapide que l'inverse.

      • [^] # Re: la vitesse d'exécution n'est pas le principal intérêt d'un compilateur à mes yeux.

        Posté par . Évalué à 5 (+4/-1).

        Les deux sont clairement intéressants.
        Un code fiable, c'est utile (parce que faire un truc inexploitable rapidement, c'est inutile), un code rapide aussi (parce que réaliser des calculs tellement lentement que le résultat est obsolète quand on l'a, c'est tout aussi inutile).
        Et il y a d'autres avantages aussi, comme la compacité du blob, la possibilité de vérifier que les dépendances sont installées (à plusieurs reprises j'ai eu ce genre de problèmes avec des paquets debian qui contenaient des applications pythons: libfoobar.so non trouvée. Amuses-toi à retrouver le paquet qui aurait dû être installé automatiquement…) via des outils comme ldd, la possibilité même de lier en statique pour avoir un truc vraiment petit et qui démarre à la vitesse de l'éclair…

        Je disais juste que, personnellement, en tant que développeur, ce que j'apprécie le plus chez les compilateurs, c'est bien le fait qu'ils peuvent me signaler quand je fais de la merde (et ça arrive assez souvent pour que je n'aie aucune envie d'utiliser sérieusement des langages interprétés).

        Si la vitesse est vraiment critique, je pense qu'il faut déjà réfléchir l'application autrement, et pas juste la passer à un compilo.
        Déjà, ça va dépendre du CPU cible: s'il a, ou non, des caches, combien de coeurs logiques sont présents, est-ce que l'application à vraiment besoin de pointeurs de 64 bits (parce que 8 octets, sur une ligne de cache, ça fait beaucoup, alors que pour pas mal d'applications 4 suffiraient probablement).
        Ensuite il y a l'architecture du soft.

        Bref, c'est toujours sympa de récupérer de la vitesse, mais si c'est critique, je doute que juste passer dans une moulinette soit la façon la plus efficace de travailler.

  • # Ça me fait penser à.. Futhark

    Posté par (page perso) . Évalué à 4 (+2/-0).

    Futhark est un compilateur du langage du même nom qui est conçu pour générer de l'OpenCL.

    Il peut même générer du PyOpenCL, et le générer comme une lib qu'on peut appeler en Python.
    Le langage est fraiment orienté calcul pur, et aussi orienté fonctionnel.
    Quelques exemples de code : https://futhark-lang.org/examples.html

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

  • # python

    Posté par (page perso) . Évalué à 8 (+7/-2).

    un code complexe comme grayscott s'exécute maintenant 15% plus rapidement que quand il était compilé avec la version 0.8.4 de Pythran

    Et quel est le rapport de la vitesse d'exécution avec l'interpréteur Python ?

    « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

  • # C'est pas la bonne blague

    Posté par (page perso) . Évalué à 2 (+2/-1).

    Demat' Nal

    C'est "Bonjour' nal" la blague. En breton, ça marche pas.

    Et il y a une erreur de version dans le lien github : https://github.com/serge-sans-paille/pythran/tree/0.8.5

  • # gain en performance *vraiment* bon

    Posté par . Évalué à 3 (+1/-0).

    Je viens de tester car je n'avais pas trop le choix et devait gagner en perf, et le résultat est bien là.

    Les erreurs de compilation sont franchement verbeuses, mais quand on est habitué au C++ on s'y retrouve.

    J'ai découvert l'intégration ipython/jupyter suite à mes tests, et c'est vraiment ce qui va rendre le truc accessible IMHO.
    J'ai eu pas mal de crash du kernel jupyter cependant, mais on s'adapte.
    Autre soucis sur le système de logging utilisé (un truc pas super standard a priori), qui corrompt le terminal/tmux, mais bon c'est pas voulu.

    En tout cas x100 sur du code quasi impossible à optimiser sans énorme changement/refactoring, ça ne se refuse pas!

    Un bémol cependant, seul un tout petit subset de numpy est accessible (les trucs triviaux de numpy.polynomials ou numpy.linalg ne sont pas disponibles), donc il faut recoder pas mal d’algorithmes à la main, ce qui est franchement dommage.

    En attendant une interopérabilité native des kernel jupyter entre eux (python, R et C++ type xeus), c'est une méthode pas mal.

    Il reste juste à mapper tout numpy (et supporter le float16!!!)

    • [^] # Re: gain en performance *vraiment* bon

      Posté par . Évalué à 1 (+0/-0).

      Par curiosité, le float16 c'est dans quel type d'application ? Uniquement pour le stockage de données, ou tu t'en sers vraiment pour réaliser les calcules ?

Envoyer un commentaire

Suivre le flux des commentaires

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