← back to the showcase

TAKT showcase: QuantLib 1.43 Monte Carlo, drop-in with bit-identical output, 2–24× faster

The numbers below are measured. The free package is on PyPI (pip install quantlib-takt); the full version is a commercial licence (see "Availability"). This directory holds the measurement scripts and every reading.

Not affiliated with QuantLib. TAKT is not affiliated with, endorsed or sanctioned by the QuantLib project or its contributors. The names QuantLib and QuantLib-SWIG are used only to identify the software we measured and build on.

QuantLib (BSD 3-clause) is a widely used C++ library for quantitative finance, with Python bindings on PyPI (the QuantLib package, ~1M downloads/month). Its Monte Carlo engines price options by simulating many price paths.

TAKT builds QuantLib 1.43 so that its Monte Carlo pricing runs several times faster, with every result identical to the official build, bit for bit on the same machine. The Python bindings and the public API are unchanged (import QuantLib); only the C++ library is replaced.

Headline

Factors are over the official QuantLib 1.43 build, by user-mode cycles:u, 95% bootstrap CIs, measured on two machines. The output was identical in every single run.

Monte Carlo case C++ Zen 3 C++ Zen 4 Python (end to end) Zen 3 / Zen 4
European options (book, Greeks, Sobol) 9.1–23× 10.1–24× 4.6–18× / 4.8–19×
Asian (control variate) 8.8× 9.3× 4.5× / 4.7×
Basket of 3 assets 6.8× 7.2× 4.4× / 4.7×
Barrier 5.7× 6.1× 4.0× / 4.3×
American (Longstaff–Schwartz) 4.2× 4.1× 3.1× / 3.1×
Heston 2.7× 2.9× 2.1× / 2.2×
Local volatility (smile surface) 2.2× 2.2× 1.9× / 1.9×

Free package vs full version

Free (pip install quantlib-takt) Full version (commercial licence)
European options MC (incl. Sobol, Greeks by bumping) accelerated accelerated
Asian, American LSM, barrier, digital original code, original speed accelerated
Basket / multi-asset original code, original speed accelerated
Heston, Bates original code, original speed accelerated
Local volatility surfaces original code, original speed accelerated
Direct path generation accelerated accelerated
Output identical to the official wheel yes, everywhere yes, everywhere
Python wheel (cp39-abi3, Linux x86-64) yes yes
C++ library (.so / .a, drop-in ABI) — yes
Free-threaded wheel (cp314t) — yes
Other platforms / QuantLib versions — on request
Support, source escrow — yes

In the free package, everything other than European Monte Carlo runs the original QuantLib code and returns the original result at the original speed. The full version accelerates all of it, with the same bit-identical output.

What was measured

One C++ driver (tools/qlmc.cpp), built against the official QuantLib 1.43 headers, runs with the library swapped: official (the library in the official PyPI wheel) versus TAKT. A Python driver (tools/qlmc.py) runs the same workloads through the wheel: the official wheel versus the TAKT wheel. Both drivers print every result to full precision (17 significant digits and the hex float), so a byte compare of their output is a bit compare. The Python driver's output is byte-identical to the C++ driver's.

Workloads (fixed seeds):

Workload What it prices
eu_book_flat book of 20 European options (3M–2Y × strikes 80–120), flat curves, constant vol, 52 steps/yr, 4,000 paths
eu_book_curve the same book on a bootstrapped yield curve, a zero-rate dividend curve and a Black variance term structure
eu_greeks_curve 1Y ATM call, 252 steps, 5,000 antithetic paths; NPV + delta, gamma, vega, rho by bumping (6 pricings)
eu_sobol_curve 1Y call, Sobol with Brownian bridge, 64 steps, 32,767 paths
asian_curve arithmetic Asian, 52 weekly fixings, control variate, 40,000 paths
american_curve American put, Longstaff–Schwartz, 100 steps, antithetic, 4,096 calibration + 8,000 paths
barrier_curve down-and-out call, 252 steps, 10,000 paths
basket_curve max-call on 3 correlated assets, 52 steps, 20,000 paths
heston_curve European call under Heston (QE martingale), 100 steps, 16,000 paths
eu_surface European call under local volatility from a Black surface with smile, 52 steps, 8,000 paths

Stands. AMD Threadripper PRO 5975WX (Zen 3), Ubuntu 24.04; AMD Ryzen 9 7950X3D (Zen 4), Debian 13. Both with the performance governor, each run pinned to one core, takt-harness 0.2.1, 9 interleaved rounds after one warm-up, user-mode cycles:u and whole-process wall time, 95% bootstrap CIs. The harness compared stdout across the builds in every run. Raw readings: results/zen3/ and results/zen4/.

C++ — AMD Zen 3

Workload Baseline wall TAKT wall cycles:u factor (95% CI) wall factor (95% CI) Output identical
american_curve 531.5 ms 136.0 ms 4.18× (4.11–4.20) 3.91× (3.86–3.96) yes
asian_curve 388.1 ms 46.5 ms 8.83× (8.76–9.01) 8.35× (8.17–8.55) yes
barrier_curve 613.7 ms 109.4 ms 5.70× (5.66–5.74) 5.61× (5.53–5.66) yes
basket_curve 636.0 ms 94.6 ms 6.84× (6.77–6.91) 6.72× (6.60–6.84) yes
eu_book_curve 738.9 ms 75.9 ms 10.09× (9.97–10.25) 9.74× (9.60–10.00) yes
eu_book_flat 633.9 ms 72.6 ms 9.11× (8.92–9.93) 8.73× (8.59–9.61) yes
eu_greeks_curve 4643.8 ms 203.5 ms 23.20× (23.06–23.44) 22.82× (22.38–23.10) yes
eu_sobol_curve 387.9 ms 44.5 ms 9.49× (9.36–9.77) 8.73× (8.47–9.26) yes
eu_surface 269.6 ms 122.9 ms 2.18× (2.15–2.20) 2.19× (2.13–2.24) yes
heston_curve 358.0 ms 136.2 ms 2.66× (2.65–2.68) 2.63× (2.58–2.66) yes

C++ — AMD Zen 4

Workload Baseline wall TAKT wall cycles:u factor (95% CI) wall factor (95% CI) Output identical
american_curve 471.7 ms 121.6 ms 4.13× (4.04–4.22) 3.88× (3.79–3.97) yes
asian_curve 349.0 ms 39.8 ms 9.27× (9.19–9.58) 8.76× (8.67–9.07) yes
barrier_curve 559.5 ms 94.0 ms 6.11× (5.82–6.22) 5.95× (5.68–6.07) yes
basket_curve 547.6 ms 79.5 ms 7.18× (7.00–7.34) 6.89× (6.76–7.08) yes
eu_book_curve 734.0 ms 68.8 ms 11.23× (9.53–11.90) 10.67× (9.14–11.31) yes
eu_book_flat 651.7 ms 65.4 ms 10.56× (9.46–11.07) 9.97× (8.56–10.77) yes
eu_greeks_curve 4199.5 ms 173.4 ms 24.44× (23.83–25.60) 24.21× (23.34–25.07) yes
eu_sobol_curve 349.8 ms 37.4 ms 10.09× (9.70–10.44) 9.34× (9.05–9.89) yes
eu_surface 232.4 ms 107.8 ms 2.18× (2.13–2.20) 2.16× (2.11–2.17) yes
heston_curve 314.0 ms 109.4 ms 2.91× (2.89–3.00) 2.87× (2.83–2.97) yes

Python, end to end and in a running interpreter — AMD Zen 3

End to end times the whole process (interpreter start, import QuantLib, building the market, pricing). "Running interpreter" repeats the workload five times in one process (the market built once).

End to end

Workload official wall TAKT wall cycles:u factor (95% CI) wall factor (95% CI) Output identical
american_curve 548.5 ms 191.0 ms 3.12× (3.08–3.13) 2.87× (2.72–2.88) yes
asian_curve 413.5 ms 104.8 ms 4.46× (4.43–4.51) 3.95× (3.88–4.01) yes
barrier_curve 627.4 ms 168.5 ms 4.00× (3.98–4.04) 3.72× (3.63–3.77) yes
basket_curve 613.6 ms 151.3 ms 4.43× (4.41–4.46) 4.06× (3.94–4.13) yes
eu_book_curve 724.6 ms 137.6 ms 5.87× (5.77–5.94) 5.27× (5.16–5.35) yes
eu_book_flat 641.9 ms 130.3 ms 5.45× (5.35–5.50) 4.93× (4.86–5.03) yes
eu_greeks_curve 4497.5 ms 264.0 ms 18.06× (17.77–18.26) 17.04× (16.38–17.36) yes
eu_sobol_curve 409.3 ms 101.1 ms 4.63× (4.55–4.65) 4.05× (3.95–4.09) yes
eu_surface 311.5 ms 174.3 ms 1.87× (1.86–1.89) 1.79× (1.76–1.81) yes
heston_curve 400.6 ms 194.2 ms 2.13× (2.07–2.15) 2.06× (1.99–2.07) yes

Running interpreter

Workload official wall TAKT wall cycles:u factor (95% CI) wall factor (95% CI) Output identical
american_curve 2424.3 ms 660.9 ms 3.79× (3.77–3.81) 3.67× (3.64–3.74) yes
asian_curve 1813.2 ms 266.6 ms 7.19× (7.17–7.22) 6.80× (6.72–6.85) yes
barrier_curve 2906.0 ms 582.8 ms 5.11× (5.07–5.13) 4.99× (4.95–5.05) yes
basket_curve 2792.7 ms 494.3 ms 5.77× (5.74–5.82) 5.65× (5.54–5.67) yes
eu_book_curve 3291.0 ms 406.2 ms 8.37× (8.32–8.44) 8.10× (8.01–8.19) yes
eu_book_flat 2944.9 ms 395.9 ms 7.70× (7.67–7.76) 7.44× (7.39–7.52) yes
eu_sobol_curve 1779.3 ms 248.1 ms 7.58× (7.52–7.61) 7.17× (7.14–7.23) yes
heston_curve 1695.1 ms 706.1 ms 2.44× (2.42–2.44) 2.40× (2.38–2.42) yes

Python — AMD Zen 4

End to end

Workload official wall TAKT wall cycles:u factor (95% CI) wall factor (95% CI) Output identical
american_curve 470.8 ms 164.7 ms 3.12× (3.08–3.16) 2.86× (2.84–2.92) yes
asian_curve 348.1 ms 84.0 ms 4.65× (4.60–4.80) 4.14× (4.01–4.25) yes
barrier_curve 547.5 ms 138.4 ms 4.26× (4.22–4.51) 3.95× (3.88–4.23) yes
basket_curve 520.5 ms 121.7 ms 4.69× (4.55–4.81) 4.28× (4.19–4.44) yes
eu_book_curve 676.9 ms 152.9 ms 5.29× (4.73–6.08) 4.43× (3.97–5.24) yes
eu_book_flat 652.3 ms 149.0 ms 5.11× (4.38–5.67) 4.38× (3.77–4.88) yes
eu_greeks_curve 4048.4 ms 225.5 ms 19.33× (19.19–20.31) 17.95× (17.38–18.63) yes
eu_sobol_curve 354.6 ms 82.8 ms 4.82× (4.75–5.03) 4.28× (4.10–4.46) yes
eu_surface 270.1 ms 147.4 ms 1.90× (1.87–1.93) 1.83× (1.79–1.87) yes
heston_curve 331.3 ms 155.9 ms 2.22× (2.21–2.27) 2.13× (2.12–2.18) yes

Running interpreter

Workload official wall TAKT wall cycles:u factor (95% CI) wall factor (95% CI) Output identical
american_curve 2144.1 ms 584.3 ms 3.77× (3.71–3.83) 3.67× (3.58–3.70) yes
asian_curve 1550.9 ms 228.0 ms 7.31× (7.20–7.50) 6.80× (6.71–7.07) yes
barrier_curve 2566.4 ms 491.4 ms 5.36× (4.86–5.44) 5.22× (4.79–5.32) yes
basket_curve 2500.6 ms 412.6 ms 6.33× (5.67–6.39) 6.06× (5.51–6.21) yes
eu_book_curve 3089.1 ms 360.7 ms 9.00× (8.67–9.52) 8.56× (8.06–8.98) yes
eu_book_flat 3046.3 ms 372.7 ms 8.80× (7.23–9.18) 8.17× (6.75–8.64) yes
eu_sobol_curve 1546.1 ms 209.0 ms 7.93× (7.85–8.01) 7.40× (7.32–7.60) yes
heston_curve 1461.6 ms 574.8 ms 2.56× (2.21–2.60) 2.54× (2.17–2.58) yes

Equivalence

"Same" means byte-identical printed output, every number at 17 significant digits and as a hex float.

Bit-identity is per system. QuantLib's results come from the system's maths library, so the official build itself prints slightly different last bits on different glibc versions (205 of the 867 values differ between glibc 2.28 and 2.39, by at most 1.5e-6 relative). The TAKT build reproduces the official build's output on the same system, bit for bit.

Where the speed-up applies, and where it does not

Availability

Reproducing the baseline

# C++: build the driver against the official QuantLib 1.43 headers, run it against each library.
g++ -std=c++17 -O3 tools/qlmc.cpp -o qlmc -lQuantLib         # with QuantLib 1.43 installed
LD_LIBRARY_PATH=/path/to/official/lib ./qlmc equiv > official.txt   # the PyPI wheel's library

# Python: price the same workloads through the official wheel and through quantlib-takt, compare bytes.
python -m venv a && a/bin/pip install -q QuantLib==1.43  && a/bin/python tools/qlmc.py eu_book_curve > a.txt
python -m venv c && c/bin/pip install -q quantlib-takt    && c/bin/python tools/qlmc.py eu_book_curve > c.txt
diff a.txt c.txt && echo identical

tools/vsbest.py and tools/table.py print the factor tables above from the readings in results/.

Contents

Source text: README.md

Telegram