Python est très utilisé en IA, en analyse de données, etc., et il a l’avantage de permettre de coder rapidement, mais le problème chronique de lenteur propre aux langages interprétés peut aussi devenir un vrai casse-tête en pratique.
Dans les projets réels, on envisage plusieurs alternatives pour améliorer les performances de Python. Il arrive aussi que le code Python ne serve qu’au prototype initial, puis qu’on le redéveloppe en Rust ou en C/C++ lors du passage en production.
Je développe expérimentalement un outil appelé Rextio comme nouvelle alternative pour résoudre les problèmes de performance sans abandonner Python.
Le concept de base consiste à convertir automatiquement en Rust les parties du code Python qui peuvent être transformées en natif (code statique avec annotations de type, etc.), puis à les compiler en binaire pour améliorer les performances, tout en laissant telles quelles les parties difficiles à convertir automatiquement en natif (code dynamique, etc.) sous forme de code Python (fallback), exécuté par CPython, afin de préserver la logique du code Python d’origine.
En gros, cela donne ceci.
Projet Python typé
-> analyse des candidats pris en charge pour le natif
-> rejet des fonctions non sûres ou non prises en charge
-> génération de Rust + PyO3 pour les fonctions acceptées
-> génération de wrappers Python de fallback pour le reste
-> build d’un artefact compatible avec import
Pour plus de détails, veuillez consulter la documentation du dépôt Git indiqué en lien.
Lorsque l’on compare l’exécution avec les binaires natifs convertis par Rextio à l’exécution du code Python d’origine avec CPython, on observe également des gains de performance.
- Exécution de code Python de base converti en natif : 57,73×
- Exécution de NumPy converti en natif : 2,52×
- Exécution de l’algorithme de Dijkstra avec NetworkX converti en natif : 3,68×
- Exécution de
Series.mapde pandas converti en natif : 66,14× - Exécution d’un deep MLP PyTorch converti en natif : 1,02× (gain limité, car les packages Python existants utilisent déjà des extensions C, etc.)
- Exécution d’une chaîne eager TensorFlow convertie en natif : 1,04× (gain limité, car les packages Python existants utilisent déjà des extensions C, etc.)
Pour le code source et les informations sur l’environnement d’exécution utilisés dans les benchmarks ayant produit ces résultats, consultez le dépôt Git rextio-benchmark.
À titre de référence, Rextio dispose d’une Core CLI qui convertit le code Python et lance la compilation, et je le développe de manière à pouvoir y ajouter des plugins supplémentaires définissant les règles de conversion de packages Python individuels en code Rust. J’ai déjà créé une partie des plugins pour NumPy et d’autres (rextio-numpy, rextio-networkx, rextio-pandas, rextio-torch, rextio-tensorflow, etc.), et les résultats de benchmark ci-dessus ont été obtenus en utilisant ces plugins.
Bien sûr, Rextio reste un projet à ses débuts, avec encore beaucoup d’améliorations à apporter, et compiler du code Python en natif basé sur Rust n’entraîne pas forcément un gain de performance dans toutes les situations.
Par exemple, si les échanges de données entre la partie native et la partie de fallback CPython sont fréquents, les conversions de données et les passages de frontière peuvent au contraire ralentir l’exécution. Cela dit, dans ce type de cas, Rextio cherche à éviter la baisse de performance en faisant basculer entièrement cette partie vers CPython, sans passer par le natif.
J’ai développé cela seul jusqu’ici, et comme le projet semble avoir atteint une certaine maturité, je vous le présente ici.
Si vous avez des questions, des avis ou des retours, je ferai de mon mieux pour y répondre et les prendre en compte.
Merci.
Aucun commentaire pour le moment.