The speculative geometry probe waited for the main line's merge on every card below 12 GB
(gpu_takes_turns), so on an 8 GB laptop card it always ran after the merge, as a serial
"Geometry check" at the end of the run (Windows RTX PRO 2000: myob 1.4-1.7 s, lyso 0.6 s,
4nwv 3.2-4.4 s, against ~0.15 s where it overlaps). Now it is decided from bytes, up front and
never from free memory:
- GPUMerge::Holds(bytes): the main line says what its merge holds of the card once the scaling
engine is ingested - the engine's DeviceBytes (an upper bound), twice where the all-observation
arm gets an engine of its own - before the post-refinement that may start the probe is let go.
A merge that has not said yet counts as leaving no room. Before the model stage it says the
whole card: model validation and MR budget 80% of the card for themselves.
- GPUWorkBeside(after_merges, bytes): the probe waits for the merges only where its own bytes
and theirs exceed 80% of the first card's total (the same 80% the merge's and the model's GPU
budgets use; on WDDM the rest is the paging margin). The image-pass / probe-pass turn-taking
below 12 GB is unchanged.
- Rugnux::IndexingProbeGPUBytes: the probe's first-pass spot workers at 24 bytes a pixel
(GPUWorkersPerCard's figure) plus 0.65 GB per FFT indexer (1.24 GB measured for two).
The spot-worker count is now one function (FirstPassSpotWorkers) for both.
- The model stage waits for GPU work beside to end before it plans its GPU engines.
Estimates on an 8.55 GB card: myob probe 4.1 GB + merge 0.6 GB -> beside (was: after);
4nwv probe 3.9 GB + merge 4.2 GB -> still after. On the RTX 5080 (16.3 GB): myob 4.8 + 0.6,
4nwv 4.5 + 8.4 = 13.0 of 13.04 GB -> beside, as before.
Concurrency only: what each pass computes is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PXc1zD1yxHqaR1DGdCTHL4