Commit a795f33
authored
Optimize leapfrog_integration
The optimized code achieves a **40% speedup** by leveraging **Numba's JIT compilation** to convert the computationally intensive N-body simulation loops from Python bytecode to native machine code. Here's why this yields substantial performance gains:
## Key Optimizations
1. **JIT Compilation with Numba (`@njit`)**: The core computation is extracted into `_leapfrog_core()` and decorated with `@njit(cache=True)`. Numba compiles this function to optimized machine code on first execution, eliminating Python interpreter overhead for:
- Nested loops iterating over particles (O(N²) pairwise interactions)
- Array indexing operations
- Arithmetic operations on distances, forces, and accelerations
The line profiler shows the original code spends ~90% of time in the innermost pairwise interaction loop—exactly where JIT compilation provides maximum benefit.
2. **Micro-optimizations within JIT context**:
- **Precomputed constants**: `soft2 = softening * softening` and `half_dt = 0.5 * dt` are computed once instead of repeatedly in loops
- **Local variable hoisting**: Position components (`pos_i0`, `pos_i1`, `pos_i2`) and masses are loaded into locals in the outer loop, reducing array accesses in the hot inner loop
- **`math.sqrt()` vs `np.sqrt()`**: Uses scalar `math.sqrt()` which is more efficient than NumPy's vectorized version for single values in JIT-compiled code
- **Explicit loop unrolling**: Acceleration reset uses explicit assignments (`acc[ii, 0] = 0.0`) instead of `fill()`, which can be better optimized by Numba
3. **Graceful Fallback**: The try/except wrapper ensures the code works identically when Numba is unavailable, maintaining portability while gaining performance where possible.
## Performance Impact Analysis
Based on annotated tests:
- **Small particle counts** (2-10 particles, few steps): 0-15% speedup or slight slowdown due to JIT compilation overhead
- **Medium workloads** (50-100 particles): 28-43% speedup as JIT benefits outweigh compilation cost
- **Large workloads** (200 particles): 39-42% speedup, demonstrating scalability
The optimization particularly benefits the `test_hundred_particles_cluster` (43% faster) and `test_two_hundred_particles_large_scale` (42% faster) cases, indicating strong performance for realistic N-body simulations. Edge cases with zero particles or zero steps show minor slowdowns due to unchanged overhead, but these are trivial execution paths.
## Why This Works
Python's interpreted nature makes tight numerical loops extremely slow. The original code's line profiler shows array indexing operations (`pos[j, 0] - pos[i, 0]`) each taking 6-7% of total runtime. Numba compiles these to direct memory accesses with zero interpreter overhead, transforming the bottleneck. The `cache=True` flag ensures compilation happens only once per function version, amortizing startup cost across multiple calls.1 parent 3a0e418 commit a795f33
1 file changed
Lines changed: 89 additions & 37 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
8 | 12 | | |
9 | 13 | | |
10 | 14 | | |
| |||
71 | 75 | | |
72 | 76 | | |
73 | 77 | | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
111 | 81 | | |
112 | 82 | | |
113 | 83 | | |
| |||
474 | 444 | | |
475 | 445 | | |
476 | 446 | | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
0 commit comments