You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf(cuda): cut two redundant scans from the weighted growth kernel
Measured, not assumed. The weighted GPU path was ~19x slower than unweighted at
d=13 (9,922 -> 525 dec/s). First ruled out the cheap explanation: it is not a
silent CPU fallback. total_failures=0, is_degraded=false, and the small-graph
dispatch does not trigger (n_edges=11,398, threshold 500). The kernel really was
running and really was that slow.
The cost was structural. Per round the weighted loop ran an O(n_checks) scan
plus three O(E) sweeps, for up to E+N+2 rounds, and passes A and B each walked
two parent chains per edge - with B recomputing exactly what A had just
computed.
Two removals, both output-neutral by construction:
* The "is any cluster still odd?" rescan is redundant. Pass A already sets
`any_growable` on the same condition: if no cluster is odd then no edge has
rate > 0. Odd-but-fully-saturated terminated through `any_growable` before too.
* Pass A now caches its per-edge rate for pass B. `parent` is mutated only by
pass C, so between A and B the two uf_find walks are guaranteed to return the
same roots and hence the same rate. Recomputing them was pure waste.
Zero extra memory: the cache reuses `support[E]`, the u8 scratch belonging to the
*unweighted* branch and therefore dead here. Safe by the kernel's own documented
contract - "the peeling phase that follows reads parent[] alone".
Proof rather than assertion. Captured every correction from the pre-change build
across d=5/9/13 x 2048 shots, rebuilt, re-ran:
BIT-IDENTICAL to baseline across 12 arrays - optimisation changed no output
CUDA-vs-CPU agreement is unchanged to the digit (67.04% / 14.06% / 0.24%), and
CUDA still matches OpenCL bitwise everywhere.
d= 5 38,548 -> 53,826 dec/s 1.40x
d= 9 2,049 -> 3,083 dec/s 1.50x
d=13 335 -> 526 dec/s 1.57x
cargo test --features full: 323 passed, 0 failed (stable over three runs).
cargo clippy --features full --all-targets: no errors.
This is a first cut, not the finish. The remaining structural win is
active-edge compaction - saturation is monotonic, so a saturated edge never
needs revisiting - which is the same frontier-vs-flat-scan optimisation the CPU
fast_uf already has. It needs a new per-thread buffer, so it is deliberately not
bundled into a change that had to prove it altered nothing.
Also exposes the GPU decoders through sinter_compat._build_matcher (weighted and
unweighted) so they are measured on the same DEM, samples and decode_batch path
as every other decoder rather than from a separate harness.
0 commit comments