Programmation et développement logiciel

Comment utiliser Numba pour accélérer les modèles Python computationnels dans les services financiers

Chad Schuster de Milliman explique comment Numba peut transformer certaines parties des programmes Python en code optimisé via LLVM, en tirant parti du traitement parallèle et des unités GPU. L’expérience présente d’importants gains de performance, mais révèle également des limites en matière de programmation orientée objet, d’inférence des types et de temps de compilation, ce qui rend crucial le choix des parties à accélérer.

2026-08-27
7 min de lecture
3,914 vues
certi.news Editorial Team
Comment utiliser Numba pour accélérer les modèles Python computationnels dans les services financiers

Chad Schuster, Principal au sein de la pratique de gestion des risques financiers de Milliman, a présenté une expérience pratique visant à construire des modèles computationnels haute performance avec Python et Numba, plutôt que de s’appuyer entièrement sur des applications écrites en C++. L’expérience part d’un problème courant dans les services financiers : les modèles qui simulent les flux de trésorerie sur un grand nombre de scénarios nécessitent une importante capacité de calcul, tandis que les équipes souhaitent conserver la rapidité de développement et la facilité de maintenance de Python.

Le problème revêt une importance particulière dans les modèles d’assurance vie et les produits de retraite tels que les annuities, où les calculs servent à évaluer les engagements futurs et à exécuter de multiples scénarios. Selon la présentation, les compagnies d’assurance se sont historiquement appuyées sur des grilles locales comprenant entre 5 000 et 10 000 nœuds, mais le passage au cloud a rendu le temps d’exécution et le coût de chaque opération plus visibles dans les décisions d’infrastructure.

Qu’apporte Numba à Python ?

Python traditionnelle, ou CPython, interprète le code pendant l’exécution, tandis que les langages compilés comme C++ transforment le code en instructions machine avant l’exécution. Numba tente de réduire cet écart grâce à la compilation juste-à-temps (Just-in-Time), en compilant les fonctions éligibles pendant l’exécution du programme à l’aide de LLVM, puis en remplaçant la fonction originale par l’implémentation compilée.

Le développeur active généralement ce processus au moyen de décorateurs Python tels que JIT ou njit. Numba fonctionne au niveau de la fonction : elle examine le code et le transforme en une représentation intermédiaire qui lui est propre, puis infère les types des variables et des paramètres ainsi que les valeurs de retour, avant d’abaisser cette représentation en LLVM IR et d’effectuer les optimisations nécessaires. Si la fonction est appelée avec des types différents, Numba peut créer des implémentations compilées spécialisées pour chaque ensemble de types grâce à ce qu’elle appelle le polymorphic dispatch.

Les gains de performance ne constituent pas un chiffre fixe

Dans la preuve de concept présentée par Schuster, Numba a rendu le programme environ 75 fois plus rapide que Python interprété. Dans un autre modèle, le résultat était différent : le transfert des calculs numériques intensifs vers Numba sur le processeur central a permis une accélération d’environ deux fois, puis le passage au GPU a apporté une accélération supplémentaire de 750 fois lors de cette exécution précise. La présentation indiquait que ce niveau d’amélioration rendait l’unité GPU à peu près équivalente à 750 cœurs utilisés lors de cette exécution, avec une réduction estimée du coût à environ un dixième.

Ces résultats ne constituent toutefois pas une promesse générale pour toutes les applications. L’amélioration dépend de la quantité de code compilable, du volume des opérations de calcul par rapport aux opérations d’entrée-sortie, de l’efficacité du Python original et de la capacité de LLVM à optimiser le code produit. En outre, le traitement sur GPU ne convient pas à tous les algorithmes ; il faut donc mesurer le véritable goulot d’étranglement avant de reconcevoir le modèle.

Qu’est-ce qui change concrètement pour les équipes d’ingénierie ?

L’expérience recommande de conserver dans Python les couches de préparation des données ainsi que les entrées et sorties, et de ne transférer vers Numba que la partie numérique intensive chaque fois que possible. Cette approche limite l’ampleur de la réécriture et préserve une grande partie de l’environnement Python, tout en concentrant les efforts d’optimisation sur les fonctions qui consomment la majeure partie du temps d’exécution. Lorsque les fonctions numériques sont limitées et clairement définies, Schuster estime que l’expérimentation avec Numba peut constituer une option directe pour ceux qui souhaitent rester dans Python.

En revanche, l’introduction d’une logique étendue et complexe dans Numba accroît les coûts de conception et de maintenance. L’expérience s’est donc appuyée sur des tableaux NumPy, des tuples et des structures de données simples, car la prise en charge de Numba ne couvre pas toutes les fonctionnalités de Python. Les limites citées comprennent les dictionnaires aux types flexibles, les exceptions, les gestionnaires de contexte, les fermetures et les listes créées au moyen de comprehensions, ainsi que la prise en charge limitée de certaines fonctions courantes telles que print, sorted et getattr.

Les limites à prendre en compte avant toute adoption

La programmation orientée objet demeure un point faible important dans cette expérience. Numba fournit des fonctionnalités expérimentales telles que jitclasses et structrefs pour apporter un comportement similaire à celui des objets, mais celles-ci peuvent changer entre les versions et ne prennent pas en charge les GPU, ce qui les a rendues inadaptées à l’approche adoptée par l’équipe. L’application s’est donc orientée vers un style plus proche de la programmation fonctionnelle et vers des structures de données simples, même si la conception orientée objet était souhaitée pour des raisons de maintenabilité et de transmission des modèles aux clients.

Les erreurs d’inférence des types et les erreurs de lowering peuvent également être difficiles à suivre, notamment dans les programmes comportant de nombreuses couches d’appels. L’erreur peut faire référence à une fonction éloignée de l’endroit où le problème est réellement apparu. Une méthode pratique proposée consiste à utiliser JIT plutôt que njit lorsque cela est nécessaire, afin de pouvoir désactiver temporairement Numba et revenir à Python interprété pour faciliter le débogage, puis réactiver l’accélération lors de l’exécution en production.

Un temps de compilation initial intervient également lors du premier appel de chaque fonction et peut augmenter lorsque la technique d’inlining est utilisée à grande échelle. Il est possible de recourir à la compilation anticipée (Ahead-of-Time) pour éviter ce délai, mais cela peut réduire la capacité du code à s’adapter à la machine effectivement utilisée par rapport à la compilation juste-à-temps.

Lecture éditoriale : la valeur fondamentale de cette expérience ne réside pas dans le chiffre de 750 fois en lui-même, mais dans la méthode qui relie la mesure des performances au découpage du modèle. Numba convient lorsque le goulot d’étranglement est computationnel et peut être isolé dans des fonctions aux types et aux structures clairs ; en revanche, transformer l’ensemble d’un système Python en code compilable peut déplacer le problème, de la lenteur d’exécution vers la complexité du développement et du débogage. Les équipes financières et d’ingénierie doivent donc mettre en balance la vitesse d’exécution, la maintenabilité, le temps de compilation et la compatibilité GPU avant de considérer Numba comme un remplacement global de C++ ou d’une refonte plus large du système.

Source de l’actualité
InfoQ - Architecture Articles
Ouvrir la source originale ↗
c
Auteur

certi.news Editorial Team

À retenir

L’expérience montre que Numba peut accélérer les fonctions Python gourmandes en calcul grâce à la compilation juste à temps utilisant LLVM, avec la possibilité d’exploiter le processeur central et les GPU. Toutefois, les gains varient selon la nature de l’algorithme, tandis que Numba impose des restrictions à la programmation orientée objet et à certaines fonctionnalités de Python. Il est donc préférable d’isoler les parties de calcul et de mesurer le goulot d’étranglement avant de l’adopter.

  • Numba utilise la compilation juste à temps pour convertir les fonctions compatibles en code optimisé via LLVM.
  • L’expérience a montré une accélération d’environ 75 fois dans un cas, ainsi qu’une accélération proche du double sur le processeur central, suivie de 750 fois supplémentaires sur GPU lors d’une exécution spécifique.
  • Il convient de conserver la préparation des données ainsi que la gestion des entrées et des sorties en Python, et de ne transférer vers Numba que les calculs numériques intensifs.
  • Certaines limitations concernent les dictionnaires flexibles, les exceptions, les gestionnaires de contexte et plusieurs fonctions courantes. Le support de la programmation orientée objet et des fonctionnalités GPU est également limité.
  • Les erreurs d’inférence des types et les opérations de lowering peuvent être difficiles à résoudre, et le premier appel peut entraîner un temps supplémentaire de compilation.
  • Les résultats doivent être mesurés en pratique, car l’accélération GPU ne convient pas à tous les algorithmes et les chiffres de performance ne constituent pas une promesse générale.

FAQ

Que fait Numba pour les programmes Python ?

Elle convertit, lors de l’exécution, les fonctions compatibles en code optimisé grâce à la compilation juste à temps et aux technologies LLVM.

Numba permet-elle toujours d’obtenir une accélération importante ?

Non. L’amélioration dépend de la proportion de code compilable, de l’intensité des calculs, de l’efficacité du Python natif, des capacités de LLVM et de l’adéquation de l’algorithme au traitement sur GPU.

Quelle approche pratique est recommandée pour utiliser Numba ?

La présentation recommande de conserver les couches de préparation des données ainsi que la gestion des entrées et des sorties en Python, et de transférer vers Numba les fonctions numériques qui consomment la majeure partie du temps d’exécution.

Quelles sont les principales limitations à prendre en compte ?

Elles comprennent le support limité de certaines fonctionnalités de Python, la difficulté de diagnostiquer les erreurs de types et les opérations de lowering, le temps de compilation initial, ainsi que l’adéquation limitée de certaines fonctionnalités de la programmation orientée objet et du GPU.

Dans la même catégorie

À lire également

Voir toutes les actualités