Programming and Software Development

How to Use Numba to Accelerate Computational Python Models in Financial Services

Chad Schuster of Milliman explains how Numba can convert parts of Python programs into optimized code through LLVM, while taking advantage of parallel processing and GPU units. The experiment demonstrates major performance gains, but also reveals limitations in object-oriented programming, type inference, and compilation time, making the selection of suitable parts for acceleration a critical factor.

2026-08-27
6 min read
13 views
فريق تحرير certi.news
How to Use Numba to Accelerate Computational Python Models in Financial Services

Chad Schuster, a Principal in Milliman’s Financial Risk Management practice, presented a practical experiment in building high-performance computational models using Python and Numba, rather than relying entirely on applications written in C++. The experiment starts from a common problem in financial services: models that simulate cash flows across a large number of scenarios require substantial computing power, while teams want to retain Python’s development speed and ease of maintenance.

The problem is especially important in life insurance models and retirement products such as annuities, where calculations are used to evaluate future liabilities and run multiple scenarios. According to the presentation, insurance companies have historically relied on local grids containing between 5,000 and 10,000 nodes, but the move to the cloud has made runtime and the cost of each operation more apparent in infrastructure decisions.

What Does Numba Add to Python?

Traditional Python, or CPython, interprets code during execution, whereas compiled languages such as C++ convert code into machine instructions before execution. Numba attempts to narrow this gap through Just-in-Time compilation: eligible functions are compiled while the program is running using LLVM, after which the original function is replaced by the compiled implementation.

Developers typically enable this process through Python decorators such as JIT or njit. Numba operates at the function level, examining the code and converting it into its own intermediate representation, then inferring the types of variables, arguments, and return values before lowering the representation to LLVM IR and applying the necessary optimizations. If the function is called with different types, Numba can create specialized compiled implementations for each set of types through what it calls polymorphic dispatch.

Performance Gains Are Not a Fixed Number

In the proof of concept presented by Schuster, Numba made the program approximately 75 times faster than interpreted Python. In another model, the result was different: moving computationally intensive calculations to Numba on the central processing unit produced a speedup of approximately two times, followed by an additional 750-fold speedup when moving to a GPU in that specific run. The presentation stated that this level of improvement made one GPU approximately equivalent to 750 cores used in that run, with an estimated reduction in cost to about one-tenth.

However, these results do not represent a general promise for every application. The improvement depends on the amount of code that can be compiled, the size of the computations relative to input and output operations, the efficiency of the original Python implementation, and LLVM’s ability to optimize the resulting code. GPU processing is also unsuitable for every algorithm, so the actual bottleneck should be measured before redesigning the model.

What Changes in Practice for Engineering Teams?

The experiment recommends keeping data-preparation and input/output layers in Python and moving only the computationally intensive portion to Numba whenever possible. This approach limits the scope of rewriting and preserves much of the Python environment, while focusing optimization efforts on the functions that consume most of the execution time. When numerical functions are limited and clearly defined, Schuster believes that trying Numba can be a straightforward option for those who want to remain within Python.

When extensive and complex logic is introduced into Numba, the cost of design and maintenance increases. The experiment therefore used NumPy arrays, tuples, and simple data structures because Numba’s support does not cover every Python feature. The limitations mentioned include dictionaries with flexible types, exceptions, context managers, closures, lists created through comprehensions, and limited support for certain common functions such as print, sorted, and getattr.

Limitations to Account for Before Relying on It

Object-oriented programming remains a significant weakness in this experiment. Numba provides experimental features such as jitclasses and structrefs to add object-like behavior, but these may change between versions and do not support GPUs, making them unsuitable for the approach adopted by the team. The application therefore moved toward a style closer to functional programming and simple data structures, even though object-oriented design was desirable for reasons related to maintainability and delivering models to clients.

Type-inference errors and lowering errors can also be difficult to trace, particularly in programs with many layers of calls. The error may point to a function far removed from the location where the problem actually originated. One practical approach suggested is to use JIT rather than njit when necessary, allowing Numba to be temporarily disabled and the interpreted Python implementation to be used for easier debugging, then re-enabling acceleration in production runs.

There is also an initial compilation time that occurs on the first call to each function, and it can grow when inlining is used extensively. Ahead-of-Time compilation can be used to avoid this delay, but it may reduce the code’s ability to adapt to the actual device compared with Just-in-Time compilation.

Editorial perspective: The core value of this experiment is not the 750-fold figure itself, but the method of connecting performance measurement with model decomposition. Numba is suitable when the bottleneck is computational and can be isolated in functions with clear types and structures; converting an entire Python system into compilable code may instead shift the problem from slow execution to development and debugging complexity. Financial and engineering teams should therefore balance execution speed, maintainability, compilation time, and GPU compatibility before considering it a comprehensive alternative to C++ or to a broader system redesign.

News source
InfoQ - Architecture Articles
Open original source ↗
ف
Author

فريق تحرير certi.news

In the same category

You may also like

View all news