Ideas
Monte Carlo Pi Approximations: C++, Julia and Python
Benchmarking execution speed and accuracy across C++, Julia and Python
My coding background began with C++ in middle school competitive programming before shifting to Python for astrophysics and cosmology projects due to its rich ecosystem (numpy, scipy, matplotlib, astropy). However, with the growing adoption of Julia in scientific computing and a desire to refresh my C++ knowledge, I set out to test how these three languages compare on a classic numerical benchmark: estimating using a Monte Carlo algorithm.
Monte Carlo algorithms are ideal for performance comparisons because they are straightforward to implement, CPU-bound, and scale effortlessly from millions to billions of iterations.
Setup
Monte Carlo methods estimate deterministic quantities using random sampling. Consider a unit square with an inscribed quadrant (or full unit circle centered at the origin). By generating uniform random coordinates within the unit square , the probability of a point falling inside the circular arc is equal to the ratio of their areas:
By counting how many points satisfy , we can approximate with increasing precision as increases.

Implementation
To ensure a rigorous comparison, each script uses high-quality random number generator and language optimisations:
| Language | Python 3.12 | C++ (g++ 13.3) | Julia 1.12 |
|---|---|---|---|
| Random Generator | numpy.random.random | std::mt19937 (<random>) | rand() |
| Execution Paradigm | Vectorised Batching | Native Scalar loop with -O3 | JIT Compilation Loop |
| Time Measurement | time | high_resolution_clock | @btime (BenchmarkTools) |
Optimisation Strategies
- C++: Standard compiled scalar loops execute directly in CPU registers with small memory usage. Compiling with
g++ -O3enables maximum compiler optimisation and instruction-level parallelism. - Julia: Julia relies on Just-In-Time (JIT) compilation. A warm-up run executes before timing to ensure LLVM compilation overhead is excluded from the benchmark.
- Python (NumPy): Pure Python loops suffer from interpreter overhead. Switching to NumPy vectorisation pushes the loops into C-level routines. To avoid allocating gigabytes of RAM when scaling up to points, computation is executed in memory-efficient batches of iterations.
All implementations and benchmarking automation scripts are available in the repository.
Results
Performance was evaluated across scale sizes ranging from to total points.
Execution Speed
The first observation is that the plot is approximately linear, which means . Though it is noteworthy, that for increasing the absolute difference between languages becomes a 2x, 4x factor which should be considered for large runs.
Unexpectedly, Julia achieved the fastest execution time, even against C++. Julia’s JIT compiler optimised scalar loops into native assembly appears to be slightly more efficient for this use case than the closely matched C++ compiled code.
Using NumPy vectorisation reduced Python’s execution times from hundreds of seconds down to competitive numbers compared with previous script drafts. This demonstrates how array batching overcomes interpreter overhead in Python’s case.
Accuracy and Convergence
According to the Central Limit Theorem, the error in Monte Carlo integration scales as . All three languages demonstrated identical convergence rates, with the absolute error decreasing reliably as sample size approached points. Small variance between runs at identical values is purely a result of differing random number engine seeds.
Conclusions
While traditional Python interpreter loops are poorly suited for raw numerical loops, modern NumPy vectorisation makes Python competitive for array-based operations on relatively small .
For maximum performance without writing C++ boilerplate, Julia provides an impressive balance: its JIT compiler generates machine code on par with optimised C++ while retaining the readable syntax of a high-level dynamically typed language.
This is my first attempt to a blog-style post on my website’s new ideas directory. If you have feedback, suggestions or any constructive comments, I encourage you to contact me. Thank you in advance!