Keeping continuous-time linearization in numeric arrays¶
The measured baseline is 46e8df3a85ba6ce6706b5b83f3791595665198aa
(the preceding compiled-query version). The candidate source is
e847ea4e6de4bd07895930f33519b943fdcd455e. The compiled benchmark scope
archives ten modules, including the factor, optimizer, MAD filter and optional
Numba adapter. It verifies every loaded module filename and all source bytes.
The optional CPU backend keeps the same thirteen numerical finite-difference evaluations in numeric arrays, avoiding repeated Python list transposition and list-to-array conversion. Ordered normal-equation kernels retain every row, left-weighted product, gradient and Hessian addition. The optimizer consumes the packed weighted system directly; public linearization still returns its existing residual/Jacobian/Hessian/gradient fields. Small/nonfinite inputs and custom factor methods retain existing behavior. Observation or transform replacement invalidates or refreshes the corresponding captures.
Captured native plane geometry skips temporary match records and unused
distance fields. Batched hybrid selection retains the scalar three-product
residual formula and first-candidate ordering. Exact residual ties still use
scalar math.dist for the centroid-distance key. Unsupported geometry and
extreme/nonfinite scores retain scalar selection. Normal-less nearest voxels
continue to reject their uniform candidate.
Observation preparation reuses the exact public-constructor normalization of immutable plane normals, retaining at most 1,024 plane captures and identity references for the first 65,536 native point tuples. Mutable/unsupported fields, changed constructors and uncaptured points use the public constructor. Prepared pose rows become native floats in 4,096-row conversion blocks.
Repeated timestamp batches reuse immutable prepared poses and numeric rows in a solve-scoped LRU with a conservative 128 MiB retained-payload budget. The full timestamp tuple and exact base-transform bytes key each entry. Changed points and extrinsics always run the ordered world-coordinate kernel again. Every cache hit updates the same interpolation/clamp/extrapolation diagnostics; a stricter extrapolation tolerance replays the original first-failure prefix. Unsupported diagnostic overrides keep the per-query path.
Adaptive tree queries accept or reject an unambiguous nearest plane in bulk
only when its conservative roundoff interval lies entirely inside or outside
the gate. Near ties, gate boundaries, tiny distances and unsupported geometry
retain the ordered scalar math.dist repair.
MAD filtering reuses the factor and its packed arrays instead of constructing and packing a second factor. Partition-based medians retain the original odd/even formulas. Stable sorting preserves the original support-floor ties and final observation order. Nonfinite or non-native residuals retain the statistics/scalar path. Retained numeric rows preserve original indices and read-only storage; public MAD results and thresholds are unchanged.
The Python default and saved schemas remain unchanged. The optional
continuous_time_query_backend: numba_cpu execution note identifies adapter
v0.2, Numba version, fastmath=false and cache=true. The arithmetic order,
sampling, temporal holdout, robust weights, damping, acceptance rules and
iteration budgets remain the same.
Complete-process measurements¶
The verified AIST GLIM Livox recording and supplied trajectory use the existing tutorial conversion. A copied point cloud is the second topic, providing an identity execution control without an independent two-sensor extrinsic or clock reference.
In the archived method IDs, sparse identifies the implementation
with dense linearization, captured geometry and prepared MAD arrays.
Default sampling budgets¶
| Metric | Baseline median (s) | Compiled median (s) | Ratio |
|---|---|---|---|
| Complete process | 11.419431 | 8.323002 | 1.37× |
| Full evaluation API | 8.706023 | 5.755083 | 1.51× |
| Clock profile + extrinsic refinement | 7.744084 | 4.860563 | 1.59× |
| Adaptive nearest-plane calls | 0.537481 | 0.186777 | 2.88× |
| Worker imports | 2.112278 | 2.023576 | 1.04× |
| Worker CPU, all threads | 12.421875 | 9.296875 | 1.34× |
| Pair | Order | Baseline wall (s) | Compiled wall (s) |
|---|---|---|---|
| 1 | baseline → compiled | 27.766257 | 16.547838 |
| 2 | compiled → baseline | 11.419431 | 8.248455 |
| 3 | baseline → compiled | 11.060818 | 8.323002 |
| 4 | compiled → baseline | 15.412262 | 10.106261 |
| 5 | baseline → compiled | 10.543867 | 7.578790 |
Baseline wall range: 10.543867–27.766257 s.
Compiled wall range: 7.578790–16.547838 s.
First candidate, own empty compiled cache: 16.547838 s (included).
| Calculation count | Baseline per run | Compiled per run |
|---|---|---|
| Uniform normal fallback | 883 | 883 |
| Interior pose interpolation | 199,892 | 99,391 |
120 target frames, all captured points¶
| Metric | Baseline median (s) | Compiled median (s) | Ratio |
|---|---|---|---|
| Complete process | 76.194248 | 32.280461 | 2.36× |
| Full evaluation API | 73.106335 | 29.003228 | 2.52× |
| Clock profile + extrinsic refinement | 70.402356 | 25.939339 | 2.71× |
| Adaptive nearest-plane calls | 4.436920 | 1.322672 | 3.35× |
| Worker imports | 2.263285 | 2.458281 | 0.92× |
| Worker CPU, all threads | 75.984375 | 33.265625 | 2.28× |
| Pair | Order | Baseline wall (s) | Compiled wall (s) |
|---|---|---|---|
| 1 | baseline → compiled | 72.863296 | 65.425788 |
| 2 | compiled → baseline | 70.815200 | 30.007821 |
| 3 | baseline → compiled | 76.194248 | 35.921352 |
| 4 | compiled → baseline | 87.984057 | 32.280461 |
| 5 | baseline → compiled | 78.327067 | 27.016137 |
Baseline wall range: 70.815200–87.984057 s.
Compiled wall range: 27.016137–65.425788 s.
First candidate, own empty compiled cache: 65.425788 s (included).
| Calculation count | Baseline per run | Compiled per run |
|---|---|---|
| Uniform normal fallback | 883 | 883 |
| Interior pose interpolation | 1,296,914 | 434,232 |
Prior candidate: default budgets¶
| Metric | Baseline median (s) | Compiled median (s) | Ratio |
|---|---|---|---|
| Complete process | 17.005656 | 16.292120 | 1.04× |
| Full evaluation API | 14.301607 | 10.530992 | 1.36× |
| Clock profile + extrinsic refinement | 13.518006 | 8.443214 | 1.60× |
| Adaptive nearest-plane calls | 0.657815 | 0.750400 | 0.88× |
| Worker imports | 2.835184 | 2.931566 | 0.97× |
| Pair | Order | Baseline wall (s) | Compiled wall (s) |
|---|---|---|---|
| 1 | baseline → compiled | 17.005656 | 16.883971 |
| 2 | compiled → baseline | 29.870457 | 17.501927 |
| 3 | baseline → compiled | 24.260037 | 16.292120 |
| 4 | compiled → baseline | 14.962965 | 11.326237 |
| 5 | baseline → compiled | 14.460176 | 9.043197 |
Baseline wall range: 14.460176–29.870457 s.
Compiled wall range: 9.043197–17.501927 s.
First candidate, own empty compiled cache: 16.883971 s (included).
| Calculation count | Baseline per run | Compiled per run |
|---|---|---|
| Uniform normal fallback | 883 | 883 |
| Interior pose interpolation | 199,892 | 199,892 |
Prior candidate: 120 target frames¶
| Metric | Baseline median (s) | Compiled median (s) | Ratio |
|---|---|---|---|
| Complete process | 56.427418 | 52.678920 | 1.07× |
| Full evaluation API | 52.966413 | 50.036244 | 1.06× |
| Clock profile + extrinsic refinement | 49.127861 | 45.401763 | 1.08× |
| Adaptive nearest-plane calls | 2.988062 | 5.972435 | 0.50× |
| Worker imports | 2.293762 | 2.045346 | 1.12× |
| Pair | Order | Baseline wall (s) | Compiled wall (s) |
|---|---|---|---|
| 1 | baseline → compiled | 83.970250 | 61.860810 |
| 2 | compiled → baseline | 75.395782 | 60.961356 |
| 3 | baseline → compiled | 56.427418 | 28.086238 |
| 4 | compiled → baseline | 51.360295 | 27.899039 |
| 5 | baseline → compiled | 51.661806 | 52.678920 |
Baseline wall range: 51.360295–83.970250 s.
Compiled wall range: 27.899039–61.860810 s.
First candidate, own empty compiled cache: 61.860810 s (included).
| Calculation count | Baseline per run | Compiled per run |
|---|---|---|
| Uniform normal fallback | 883 | 883 |
| Interior pose interpolation | 1,296,914 | 1,296,914 |
Each configuration contains five paired fresh interpreters. Order reverses every other pair. Each method has its own initially empty compiled cache; all first compilation, imports and later cache loading are included. Metadata records the cache file hashes before and after every run. All timings remain, without warmup, outlier exclusions or changed point budgets.
Wall includes interpreter startup, imports, replay, every clock candidate and extrinsic refinement, holdout diagnostics, all input hashes, YAML output and measurement save. Parent source/input audits and CLI presentation are outside that timer. Phase timers and counters wrap existing calls, with their overhead included. Optional instrumentation selection reads the config during startup, also inside wall time. These are local descriptive observations with persistent OS caches and unrelated activity; they are not portable confidence estimates. The worker CPU diagnostic sums all worker threads from entry through the saved-result hash. It excludes interpreter startup and measurement-JSON serialization; complete-process wall time includes both. CPU and wall times are reported separately, without normalizing or replacing observed timings.
The unchanged default configuration captures 3,000 source records and 36 target frames with 400 points each, selecting 6,000 train and all 3,200 holdout targets. The unchanged full-capture configuration uses 120 frames and all 38,400 train / 9,600 latest holdout targets. Both keep the existing MAD/Huber settings, initial estimates, temporal partitions and bounded optimization. No additional subsampling or approximate nearest search is introduced.
The default result retains rank 6, six clock rounds, 4,773 train / 2,526 holdout
correspondences, -0.04 s selected offset and holdout RMSE 0.05078387183780445 m.
The full-capture result retains rank 6, eight clock rounds, 29,181 train / 3,451
holdout correspondences, -0.025 s selected offset and holdout RMSE
0.0922906037408748 m. Its status remains max_iterations; the acceleration
preserves that bounded outcome and does not claim convergence or an absolute
clock reference. Holdout never chooses the solution.
All 20 current and 20 prior API results are checked against their actual schema-valid saved YAML, raw file hashes and full canonical payload hashes. Within each separately measured configuration/source cohort, every value and provenance field matches except the exact declared optional execution identity note (adapter v0.1 versus v0.2). Full unfiltered payloads and hashes remain in the published trials. The comparison preserves every other note, candidate score, transform, offset, rejection, diagnostic, reason and status. Ordered point-index/capture-timestamp/XYZ hashes bind the unchanged disjoint train and holdout samples. Ratios compare these same complete runs; earlier gains and profiler times are not multiplied into them.
Validation and provenance¶
Local validation: 464 relevant tests passed, one optional integration skipped; Ruff and strict mypy passed; all 126 exported schemas remain byte-identical. Tests cover float-bit residuals, numerical Jacobians, weighted/unweighted normal equations, complete solver histories and diagnostics, hybrid ties, missing candidates, frozen field captures, cache bounds, invalidation, custom methods, MAD thresholds and support-floor ordering. Complete public-data results retain all quality judgments and provenance.
The four definitions and recomputed aggregates retain all trials and canonical
payloads. publication-index.json binds exact Git source/config archives,
definitions, aggregates, conversion lineage and the publication launcher.
Original measurement hashes and working source hashes remain in the index.
Archives use LF; publication checks that only line endings differ from working
bytes. Private executable/workspace prefixes become placeholders. Compiled
binaries stay in local runtime caches and are not published.
The preceding candidate 09c346935c610ed32517f31772e4be46090b5817 is retained
separately in prior_default_budget.* and prior_full_capture.*. Its five-pair
wall medians were 17.005656 → 16.292120 s (1.04×) and
56.427418 → 52.678920 s (1.07×), respectively. Those measurements motivated
the additional bounded pose reuse and bulk adaptive gates. They remain full
separate cohorts with their original payloads, source revision and timings;
they are not discarded or pooled with the current candidate. Changed source
archives are named prior.*, with the same baseline and public inputs.
The recorded Git revisions in result and train-diagnostic provenance differ
between the prior and current cohorts and are preserved. The launcher verifies
those two exact expected revisions separately when checking cross-cohort
numerical parity; strict within-cohort comparisons exclude only the declared
execution identity note.
Official inputs and conversion lineage match the preceding fixture. The raw
bag MD5 is fb17a6d4e0bc1765e276f0dcca8a5063 (613,350,674 bytes) and the
GT archive MD5 is ea25f7703ec5d076ba91dba63666d92c (140,570 bytes).
conversion-provenance.json binds the trajectory, converted database/metadata
and original clock-normalization command. AIST Zenodo record 6864654 licenses
the data under CC-BY-4.0.
Reproduce¶
Prepare the recording with the
verified public-data instructions and
install python -m pip install -e ".[numba]". At the measured candidate commit,
keep source, config and inputs fixed, and use a new output folder per cohort:
python tools/benchmark_adaptive_plane_search.py \
--baseline-scope compiled \
--baseline-commit 46e8df3a85ba6ce6706b5b83f3791595665198aa \
--config examples/public_datasets/glim_versatile/online_continuous_time_compiled_queries_config.yaml \
--numba-cache-policy persistent \
--repetitions 5 --output-dir outputs/glim-linearization-default
python tools/benchmark_adaptive_plane_search.py \
--baseline-scope compiled \
--baseline-commit 46e8df3a85ba6ce6706b5b83f3791595665198aa \
--config examples/public_datasets/glim_versatile/online_continuous_time_compiled_full_capture_config.yaml \
--numba-cache-policy persistent \
--repetitions 5 --output-dir outputs/glim-linearization-full
--numba-cache-policy cold gives every process a separate empty cache; report
that alternative protocol separately. The ordinary calibration command applies
the acceleration with the existing optional-backend configuration:
calibrex continuous-time-lidar-pair \
examples/public_datasets/glim_versatile/online_continuous_time_compiled_full_capture_config.yaml \
--output outputs/glim-linearization.yaml