Journal Pythran 0.7.2 - détails techniques

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
28
15
oct.
2015

Termi' Nal (humour du 42ème degré),

Pythran, compilateur open source dédié au Python scientifique, vient tout juste de sortir sa version 0.7.2, à l'occasion de PyConFR où il sera présent. Ceux qui ont loupé la saison 1 de ce magnifique compilateur seront peut-être intéressés par le tag pythran.

Au lieu de vous résumer le Changelog, le reste de ce journal va vous parler de deux points techniques, un sur boost.python, et l'autre sur C++11. Moins de pub, plus de techno !

Suppression de Boost.Python

Depuis sa création, Pythran reposait sur Boost.Python pour exporter du code C++ dans un module Python natif. C'était assez haut niveau, on pouvait pas mal customiser plusieurs aspects, pleins de trucs étaient gérés :

  • support de la Surcharge de fonction
  • possibilité d'injecter de la doc visible depuis Python (les docstrings)
  • possibilité de définir ses propres convertisseurs de type
  • gestion des exceptions et traductions en exception Python

Avec un minimum d'effort. Pour les non habitués, un exemple tout droit sorti de la doc :

#include <boost/python.hpp>

BOOST_PYTHON_MODULE(hello_ext)
{
    using namespace boost::python;
    def("greet", greet);
}

qui permet d'exposer depuis du code C++ la fonction greet. Un peu de meta-programation est utilisé pour éviter au dev d'avoir à spécifier les types de paramètres, c'est très élégant !

Mais derrière cette vision idyllique se cachait deux défauts :

  1. Lent lent lent, que c'est lent. Pas à l'exécution (à par peut être le système d'enregistrement des convertisseurs de type et d'exceptions à l'initialisation du module, mais ça ne se paie qu'une fois), mais à la compilation. Sur 2s de compilation d'un petit code Python par Pythran. On pouvait passer presque 25% du temps dans le compilateur C++ à se balader dans les en-tête de Boost, à instancier des milliers de template, à dérouler des macros de partout. Du C++ dans toute sa splendeur !

  2. Boost.Python n'est pas une bibliothèque « header only ». Du coup le code C++ généré par pythran doit être lié avec boost. Ça peut paraître banal au lecteur de LinuxFR, mais beaucoup d'utilisateurs de Pythran travaillent sous OSX, ou sont des scientifiques avec une vision très « outil » de leur machine. Et installer boost, c'est parfois trop pour eux. Idem sous Windows. Donc pas mal de soucis d'install. Et il faut dire que le nommage des libs boost, entre libboost-python-mt.so, libboost-python.so, boost_python-vc71-mt-1_32.dll, ça n'aide pas (même si c'est justifié hein).

Au final, en adaptant les convertisseurs de types écrits pour Boost.Python et en demandant au compilateur Pythran de générer la glue Python/C, on arrive au même résultats avec des temps de compilation moindres, un temps de chargement de module inférieur, et moins de dépendances à l'installation.

Et voilà, encore un gros échec d'ingénierie et de réutilisation de code !

La move semantics dans toute sa splendeur

Vous n'êtes pas sans savoir que C++11 a introduit un nouveau type de référence, les r-value references pour désigner un objet temporaire, non assigné à une variable, qui se trouve généralement à droite d'un signe égal, d'où le nom.

Et bien c'est fou les trucs qu'on peut faire avec. Prenez ce code Python/numpy :

import numpy as np

def foo(n):
  a = np.random.rand(n)
  return a + 3

Une des optimisations de pythran va être de le transformer de cette façon :

def foo(n):
  return np.random.rand(n) + 3

Et le code C++ généré aura la même gueule et le truc sympa, c'est la gestion du transfert de propriété qui est très bien gérée par C++, pour peu que l'on fasse attention. Plus exactement on peut spécialiser l'opérateur+ entre le tableau généré par np.random.rand(n) et le scalaire 3, avec une méthode surchargée pour les instances temporaires

ndarray<T, N> ndarray<T, N>::operator+(T) &&;

ce qui permet d'implémenter un comportement du genre « ceci est un appel de méthode sur un objet temporaire, donc je peux construire le tableau de retour en réutilisant la mémoire de l'instance courante ». Et ça c'est la top classe ! Dans ce cas précis c'est même mieux qu'une expression template !

Pleins d'opportunités pour ce genre d'optimisations dans Pythran, c'est chouette, et ça conclut de façon enthousiasste cette bafouille !

  • # PyConFR

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

    Oubli : coup de Pau, je serais à PyConFR ce week end, l'occasion de parler IRL !

    • [^] # Re: PyConFR

      Posté par  . Évalué à 3.

      Aller à Pau, c'est quand même pas de la Tarbes depuis Paris.

  • # Réinventer la roue

    Posté par  . Évalué à 3.

    Et voilà, encore un gros échec d'ingénierie et de réutilisation de code !

    Soit en fier !

    La roue que tu utilisais était bien mais elle ne tournait pas assez vite et n'était pas tout terrain.

    • [^] # Re: Réinventer la roue

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

      Soit en fier !

      http://sensmotdire.gnunux.info/:%C3%AAtre.html

      (cf. impératif)

      de rien.

    • [^] # Re: Réinventer la roue

      Posté par  . Évalué à 6. Dernière modification le 16 octobre 2015 à 02:56.

      Comme BAud…

      Faute assez surprenante vu qu’à l’oral on fait souvent la liaison (je ne saurais dire si elle est obligatoire ou simplement conseillée par contre) : soizenfier

      Voilà, je réponds sur la forme et non sur le fond, je n’en suis même pas désolé ! ^^

      • [^] # Re: Réinventer la roue

        Posté par  . Évalué à 1.

        Faute assez surprenante vu qu’à l’oral on fait souvent la liaison

        Le réflexe d'écrire 99.9% du temps soit, je n'ai même pas vu la faute…

  • # pybind11

    Posté par  . Évalué à 6.

    Je ne sais pas si c'est pertinent, mais je viens d'apprendre l'existence de pybind11, qui a pour objectif de fournir des primitives similaires à Boost.Python, mais sans boost.

    • [^] # Re: pybind11

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

      Super classe ! C'est une des options que j'avais envisagée (d'écrire un boost.python à la sauce c++11) mais on n'avait besoin que d'un sous ensemble… Là ça a l'air classouille !

Suivre le flux des commentaires

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