Numba, l'optimiseur Python spécialisé dans le calcul numérique, est sorti en version 0.22.1. Numba est un compilateur juste-à-temps (JIT ou JàT) pour Python, basé sur LLVM, permettant d'optimiser du code de calcul numérique, notamment basé sur Numpy. Cette nouvelle version participe du processus habituel de sorties (une nouvelle version tous les un à deux mois) et apporte son lot de nouvelles fonctionnalités et de corrections de bugs.
Sommaire
- Qu'est-ce que Numba ?
- Alternatives
-
Nouveautés de la version 0.22
- Prise en charge de Python 3.5 et Numpy 1.10
- Compilation hors ligne
- Améliorations de la vectorisation automatique
- Améliorations de l'indexation des tableaux
- Optimisation de la mise en cache des fonctions
- Passage de listes en paramètre d'une fonction
- Tri de tableaux et de listes
- Corrections pour ARMv7
Qu'est-ce que Numba ?
Le but de cette dépêche n'est pas de faire une présentation détaillée de Numba et le lecteur est renvoyé à la dépêche précédente sur Numba 0.14.
En résumé, Numba est un compilateur juste-à-temps, sur demande, prenant en charge un sous-ensemble de Python et permettant d'accélérer les calculs scientifiques réalisés avec ce langage et la bibliothèque Numpy. En échange de ces limitations, le code compilé avec Numba approche ou égale habituellement la vitesse d'un code équivalent écrit en C ou Fortran. Numba permet également de compiler du code Python pour l'exécution sur un GPU, avec à la clé un potentiel d'accélération encore plus grand.
Alternatives
Il existe quelques alternatives à Numba :
- Pythran est un compilateur hors-ligne produisant une extension compilée en C++ après traduction de votre code Python en C++
- Cython permet de coder des modules d'extensions dans un sur-ensemble de Python, avec des annotations optionnelles
- PyPy est une implémentation alternative de Python bien connue, qui intègre un compilateur juste-à-temps prenant en charge l'ensemble de la sémantique de Python
Nouveautés de la version 0.22
Prise en charge de Python 3.5 et Numpy 1.10
Numba fonctionnait déjà avec Python 2.6, 2.7, 3.3 et 3.4, ainsi que Numpy 1.6 à 1.9. Cette nouvelle version ajoute la prise en charge de Python 3.5 et Numpy 1.10. Cela ne veut pas dire que les fonctionnalités ajoutées à ces nouvelles versions sont toutes prises en charge, mais que les fonctionnalités pré-existantes marchent correctement et sont validées par la plateforme d'intégration continue (constituée d'un premier niveau, sous Linux seulement, avec Travis-CI, et un deuxième niveau intégrant Linux, OS X et Windows sur un jeu de machines interne à Continuum). De plus, des paquets binaires sont fournis sur la plateforme Anaconda.
Compilation hors ligne
Numba fournit désormais une fonctionnalité de compilation hors ligne (Ahead of Time en anglais) permettant de créer, à l'instar de Cython ou Pythran, un module d'extension compilé contenant les fonctions désirées. Cette fonctionnalité existait déjà en interne mais n'était pas documentée à cause de trop nombreuses limitations. Une bonne partie de ces limitations est désormais levée, et une intégration avec distutils
et setuptools
a été ajoutée.
La compilation juste-à-temps reste le cas d'usage privilégié de Numba, mais ce mode de compilation alternatif permettra à ceux qui le désirent de distribuer du code compilé sans dépendance à Numba, et une réduction des coûts de démarrage.
Améliorations de la vectorisation automatique
Des fonctionnalités qui étaient auparavant uniquement fournies dans l'extension propriétaire de Numba, NumbaPro, sont désormais disponibles dans le projet de base. Elles incluent :
- l'ajout du parallélisme automatique pour les fonctions universelles compilées par Numba : dans ce mode, le calcul est automatiquement distribué sur autant de fils d'exécution matériels que n'en expose le CPU
- une fonction permettant de générer automatiquement des réductions en CUDA : une réduction consiste par exemple à générer la fonction somme (d'un tableau) depuis l'opérateur d'addition ; implémenter efficacement une réduction en CUDA n'est pas trivial, car il faut choisir une taille optimale pour les blocs de threads, et synchroniser correctement les accès aux tableaux de résultats partiels
- la possibilité de compiler des fonctions universelles pour l'exécution en CUDA (et aussi sur les architectures HSA d'AMD)
Améliorations de l'indexation des tableaux
Les tableaux Numpy peuvent être indexés de multiples façons (totale, partielle, par entiers, par plages d'entiers, par tableaux de booléens, etc.). Numba comprend désormais toutes les possibilités d'indexation basique et un sous-ensemble des possibilités d'indexation farfelue (ou fancy indexing).
Optimisation de la mise en cache des fonctions
Numba propose de manière optionelle (désactivée par défaut), de mettre en cache les fonctions compilées juste-à-temps, permettant de réduire largement les temps de compilation. Cette mise en cache procédait auparavant à une sérialisation de la représentation intermédiaire (IR) LLVM, elle sauvegarde désormais le code objet final de la fonction, permettant un gain de temps additionnel.
À noter que cette fonctionnalité est distincte de la compilation hors-ligne, bien que ses bienfaits puissent sembler similaires.
Passage de listes en paramètre d'une fonction
Numba ne permettait pas de passer une liste Python à une fonction compilée, car les modifications faites à la liste par la fonction n'étaient pas visibles par l'interpréteur. Cela est désormais autorisé, et les modifications sont répercutées à la fin de l'exécution de la fonction.
Ce nouveau comportement peut sembler étrange, mais est dû au fait que Numba transforme d'abord la liste Python en un vecteur natif. Par exemple, la fonction native reçoit un tableau linéaire d'entiers 64 bits plutôt qu'un tableau de pointeurs vers des objets typés.
Tri de tableaux et de listes
Numba implémente désormais la méthode sort()
sur les tableaux et les listes, ainsi que la fonction standard sorted()
. L'algorithme utilisé est un tri rapide assez simple ; il n'est donc pas stable, ce qui ne pose pas de problème, étant donné l'éventail des types de données actuellement pris en charge.
Pour l'anecdote, le tri rapide est, dans les cas non-triviaux, beaucoup plus rapide que timsort (l'algorithme standard de CPython) sur des tableaux de données natives ; cela rejoint l'expérience de Java, qui utilise un tri rapide pour les types valeur et timsort pour les types objet.
Corrections pour ARMv7
Des changements ont été effectués pour réussir à faire tourner la suite de tests sans erreurs sur une machine armv7l (en l'occurrence, un ODROID-XU4, mais le résultat devrait également fonctionner sous un Raspberry Pi 2). Notons qu'ARM n'est cependant pas officiellement pris en charge : il n'y a pas d'intégration continue sur ces architectures.
Aller plus loin
- Dépêche précédente (Numba 0.14 + présentation du projet) (69 clics)
- Site officiel (page d'accueil) (137 clics)
- Documentation (38 clics)
- Page Github (code et suivi de bugs) (23 clics)
- Notes de version (27 clics)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.