URL: https://linuxfr.org/users/serge_ss_paille/journaux/pythran-0-7-2-details-techniques Title: Pythran 0.7.2 - détails techniques Authors: serge_sans_paille Date: 2015年10月15日T08:38:36+02:00 License: CC By-SA Tags: pythran, compilation et c++ Score: 28 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](https://linuxfr.org/tags/pythran/public). - [Site du projet](http://pythonhosted.org/pythran) - [Sur GitHub](https://github.com/serge-sans-paille/pythran) - [Sur Pypi](https://pypi.python.org/pypi/pythran) - [Sur Conda](https://anaconda.org/serge-sans-paille/pythran) Au lieu de vous résumer le [Changelog](https://github.com/serge-sans-paille/pythran/blob/master/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](http://www.boost.org/doc/libs/1_59_0/libs/python/doc/index.html) 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](https://fr.wikipedia.org/wiki/Surcharge_%28programmation_informatique%29) - 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_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 : ```python 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 : ```python 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 ```c++ ndarray ndarray::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](https://en.wikipedia.org/wiki/Expression_templates) ! Pleins d'opportunités pour ce genre d'optimisations dans Pythran, c'est chouette, et ça conclut de façon enthousiasste cette bafouille !

AltStyle によって変換されたページ (->オリジナル) /