Captured CUDA residual summaries: experimental, disabled by default¶
Moving already-captured residual summaries to CUDA did not establish a reliable whole-pipeline gain. The dense ratio of medians is 0.914x (about 9% slower), while its median paired ratio is 1.130x. Keep the existing ordered CPU summary route by default. The direct Python API permits explicit experiments; configuration and result schemas stay unchanged.
from calibrex.solvers.continuous_time_lidar_pair_solver import ContinuousTimeLidarPairOptions
options = ContinuousTimeLidarPairOptions(
query_backend="cuda",
cuda_captured_summary=True, # Experimental; benchmark the complete workload.
)
Computation and ownership¶
Only native factors with at least 8,192 observations can use the CUDA summary route, and only after finite differences have captured that exact immutable observation payload. The summary never captures or uploads new observations. An exact transform cache match borrows read-only host residuals; otherwise the existing FP64, no-FMA residual kernel evaluates the captured device arrays. Ordered CPU summation retains CPython 3.10/3.11 plain addition and CPython 3.12 compensation, followed by Python division and square root. Unsupported runtimes, uncaptured data and initial/holdout summaries retain the existing CPU route. Small batches do not import CUDA for this operation.
Fresh summaries still upload a 56-byte transform and download residual values. This avoids extra observation uploads, not all transfers. Owned streams and locks retain caller stream state and serialize shared contexts. Cached finite differences are not evicted by summary requests. Forks remain empty; public residual and linearization outputs remain owned. Public hooks, robust loss, diagnostics and optimizer histories are preserved.
All whole-process observations¶
Three alternating pairs each for dense and full capture, plus five for default sampling, use independent initially empty persistent Numba/CuPy caches per workload and method. Every first compilation, cold observation and slower trial is retained. Whole wall includes startup, imports, replay, all candidates/refinements, transfers, diagnostics, hashes and saves. Parent audits are excluded; OS caches persist. No current CPU-only cohort was run. These cohorts are not pooled or multiplied by earlier ratios.
| Workload | Baseline whole median | Experimental whole median | Ratio of medians | Median paired ratio |
|---|---|---|---|---|
| 960,000 captured points | 35.314477 s | 38.644438 s | 0.914x | 1.130x |
| 48,000 captured points | 19.251234 s | 17.538761 s | 1.098x | 1.098x |
| Default sampling | 7.490853 s | 6.837300 s | 1.096x | 0.982x |
Default sampling never runs the new CUDA summary. Its 1.096x ratio of medians and 0.982x median paired ratio do not establish a consistent gain or resolve the preceding small-batch timing variation.
| Workload | Pair | Order | Baseline whole wall | Experimental whole wall |
|---|---|---|---|---|
| dense | 1 | baseline, experimental | 49.512418 s | 43.797816 s |
| dense | 2 | experimental, baseline | 34.254949 s | 29.544137 s |
| dense | 3 | baseline, experimental | 35.314477 s | 38.644438 s |
| full | 1 | baseline, experimental | 19.251234 s | 17.538761 s |
| full | 2 | experimental, baseline | 8.675902 s | 7.592925 s |
| full | 3 | baseline, experimental | 22.847606 s | 22.517647 s |
| default | 1 | baseline, experimental | 19.181053 s | 16.474535 s |
| default | 2 | experimental, baseline | 8.585596 s | 10.154833 s |
| default | 3 | baseline, experimental | 7.490853 s | 6.458327 s |
| default | 4 | experimental, baseline | 6.638537 s | 6.760881 s |
| default | 5 | baseline, experimental | 6.700437 s | 6.837300 s |
All 22 complete formal results match after path separator normalization
and exclusion of strictly validated execution identity notes. Full API
results, unchanged saved YAML bytes, histories and diagnostics are retained.
Dense sampling uses 768,000 train and 192,000 holdout targets; full capture
uses 38,400 and 9,600. Both finish at rank 6 with max_iterations.
Default sampling uses 6,000 and 3,200 and finishes at rank 6 with converged.
Actual work outside formal timing¶
The independent dense diagnostic records 102 additional GPU residual kernel launches over 59,724,347 rows. Its GPU summary cache hits are zero; cache borrowing is covered separately by actual-device tests. CPU full-observation summaries decrease from 154 to 52 calls, retaining 16,950,268 CPU rows; GPU values are reduced in order on CPU. The diagnostic exactly matches the first formal experimental result.
| Execution counter | Count |
|---|---|
gpu_linearization_calls |
56 |
gpu_linearization_requests |
129 |
initial_rank_calls |
26 |
initial_rank_compiled |
26 |
gpu_linearization_cache_hits |
73 |
max_per_context_cache_bytes |
33,398,792 |
gpu_linearization_rows |
32,768,988 |
gpu_residual_calls |
0 |
gpu_residual_rows |
0 |
gpu_payload_uploads |
26 |
gpu_payload_bytes |
2,066,730,664 |
cpu_linearization_calls |
0 |
cpu_residual_calls |
53 |
cpu_summary_calls |
52 |
gpu_summary_calls |
102 |
gpu_summary_rows |
59,724,347 |
gpu_summary_requests |
102 |
gpu_summary_cache_hits |
0 |
cpu_summary_rows |
16,950,268 |
discarded_residual_lists_avoided |
102 |
discarded_residual_rows_avoided |
59,724,347 |
cpu_normal_calls |
129 |
cpu_uniform_query_calls |
0 |
cpu_adaptive_query_calls |
0 |
cpu_adaptive_repaired_rows |
0 |
compiled_packing_calls |
52 |
compiled_packing_rows |
24,960,000 |
cpu_distinct_centroid_tie_rows |
307,670 |
compiled_replay_calls |
120 |
compiled_replay_rows |
960,000 |
gpu_plane_query_calls |
52 |
gpu_uniform_query_rows |
24,960,000 |
gpu_adaptive_query_rows |
24,960,000 |
gpu_map_upload_bytes |
105,635 |
gpu_query_upload_bytes |
1,198,080,000 |
gpu_residual_calls=0 counts the public standalone residual API;
gpu_summary_calls=102 counts the private captured summary kernels.
Input payload uploads, finite differences, query work and CPU ordered
normal equations retain their work. Extra GPU coverage does not imply
a whole-process gain.
| Instrumented phase | Pre-change call sum | Experimental call sum |
|---|---|---|
CudaPlaneQueries.query |
11.103964 s | 6.203211 s |
compiled_packing |
5.690168 s | 2.649909 s |
_PackedObservationBuilder.build |
17.558993 s | 9.290624 s |
cpu_residual_calls |
5.282785 s | 2.956381 s |
cpu_summary |
18.527361 s | 3.002949 s |
gpu_linearization |
12.036049 s | 10.468887 s |
cpu_normal_calls |
3.694416 s | 2.786667 s |
gpu_captured_summary |
— | 2.425454 s |
cpu_captured_summary_reduction |
— | 0.194925 s |
Call sums nest and overlap across concurrent candidates and include instrumentation. They are neither critical-path percentages nor formal phase speedups. Timings vary substantially; no portable confidence estimate or peak memory measurement is claimed.
The retained pre-change pose probe finds only 35,328 adjacent repeated poses among 15,196,549 observation rows (about 0.23%). A consecutive-pose grouping optimization was therefore not implemented.
Provenance, final policy and reproduction¶
Measured auto-enabled implementation: 4c3204637f94ec7f573df21f8fdec3535b13b362.
Previous GPU control: f59c2b84c93f4fb06ea6b069d139b8adf2936d40.
Final default-disabled API policy: 18ee25541d32bf66399a3f3521121d30471cf4e4.
Formal timings describe the measured auto-enabled implementation. The final policy revision only adds the explicit boolean option, its dispatch guard and validation. Its default-disabled behavior was tested with complete synthetic CPU/CUDA clock profiles; this revision was not used for a new formal timing cohort. Enabling the option selects the measured summary path. The final source and test bytes are archived separately.
Targeted validation: 270 tests passed, Ruff passed, mypy passed over 356 source files, and all 126 generated schemas are byte-identical to the base. Tests cover actual streams, shared-context concurrency, empty/forked and replaced payloads, cache ownership, both summation policies, robust losses, default-disabled dispatch, explicit opt-in, histories and logical counters.
Use an isolated checkout of the measured commit to reproduce the frozen
run-captured-summary-v1.py.txt launcher; it expects the verified public
inputs and writes the original three output cohort directories.
diagnose-captured-summary-v1.py.txt reproduces the instrumented dense
control on that measured checkout after the formal cohorts.
The launchers are archived unchanged and do not enable the final option
when run on a later checkout. Hashes bind 20 measured sources, 14 preceding
GPU modules, configs, launchers and every result. Measured checkout line
endings are preserved; only execution-location metadata is made portable.
The public GLIM sensor is copied into two topics as an execution parity control. This does not establish independent two-sensor calibration accuracy. No raw sensor data or hardware model identifier is published here.