Profiling-driven C++ acceleration of the two numeric hotspots in a real-time stereo perception loop, exposed to Python via pybind11 / Eigen. Drop-in: the C++ kernel and a bit-for-bit pure-Python reference implement the same contract, and the package works with or without the compiled extension.
Profiling a real-time stereo tracking loop found two per-frame hotspots:
ransac_disparity— a 20-iteration consensus loop, ~385 µs/call in pure Python.kf_predict/kf_update— tiny-matrix Kalman steps where NumPy's per-call Python overhead dominates the actual arithmetic.
Both are pure numeric functions (NumPy in / NumPy out), so they move to C++ without changing the calling architecture: adaptive process noise, the gating decision and NIS telemetry stay on the Python side.
perception_accel/_fallback.pyis the reference pure-Python implementation.- The C++ extension (
_accel) must match it to within tolerance —tests/test_accel.pyverifies this over 2000 randomized cases (predict, update, NIS, gating) plus RANSAC behavior. - If the compiled extension is absent, the package transparently falls back to Python
(
USING_CPPtells you which path is active). Nothing breaks if C++ isn't built.
Requires g++ (C++17), pybind11 (pip) and Eigen3.
cd perception_accel && ./build.sh # produces _accel*.sopython3 tests/test_accel.pyThe test asserts C++ ≡ Python equivalence, correct gating/RANSAC behavior, and that the C++ path is faster. It passes on the pure-Python path too (skipping the speed asserts).
import perception_accel as accel
d = accel.ransac_disparity(disparities, 20, 10, 0.15, 0.40, seed=0)
x2, P2 = accel.kf_predict(x, P, F, Q)
status, nis, innov, x3, P3 = accel.kf_update(x, P, H, R, z, chi2=9.21, gating=True)| Hotspot | Pure Python | C++ | Speedup |
|---|---|---|---|
ransac_disparity (20 iterations) |
343 µs | 32 µs | 10.7× |
kf_predict + kf_update (6-state) |
18 µs | 6 µs | 3.0× |
Median of 5 runs of tests/test_accel.py on an AMD Ryzen 5 7640HS, built with
g++ -O3 -march=native. Measured, not estimated — reproduce it with one command.
RANSAC gains the most because the 20-iteration consensus loop is pure interpreter overhead;
the Kalman kernels gain less because they mainly shed NumPy's per-call dispatch cost.
MIT — see LICENSE.