Repository navigation
Conversation
…roducible without sorting - wgslFunctions.wgStableRank: stable ranking by digit across a workgroup (GPU Multisplit, Ashkiani et al. TOPC 2017): subgroupDigitMatch within a subgroup, one counter row per subgroup, subgroup-blocked positions so the order does not depend on the subgroup size. Needs subgroups >= 32 wide. - MultisplitPerm option ranking: "atomic" (default, unchanged) | "stable". Stable ranks the scatter with wgStableRank, gives each workgroup a contiguous run of tiles (hist and scatter), and places the finish's sub-buckets with wgStableRank. Every group then arrives in index order, so the output is reproducible with no sub-bucket or overflow sort; reference() models it. Default groups of 2,048 (no sort cost). - Regression tests for stable (when subgroups >= 32): keys, indices with several tiles per workgroup, three passes, the overflow path, Philox pairs, and 2^20 in the large tests. - examples/multisplitperm_bench_node.mjs: atomic vs reproducible vs stable, and Philox pairs atomic vs stable, with GPU timestamps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Collaborator
Author
|
Closing as a measured negative result. Stable (ballot-ranked) multisplit is correct everywhere tested: simulated RDNA4, M1 Max and V100, 133/133 each. It is slower than reproducible-by-sorting at every size, so it buys nothing. G elements/s, keys, default group sizes (
Stable runs at 0.27–0.35× of atomic on Apple and 0.57–0.69× on the V100; reproducible-by-sorting runs at 0.67–0.86×. An 8-bit pass costs 8 ballots per element, plus a counter update and shuffle per round. Workgroup atomics are cheap on both GPUs, especially Apple. This agrees with Ashkiani et al.: ballot ranking pays off only with few buckets. The branch stays as a record. Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 3 of the GPU Multisplit plan: a prototype of a stable multisplit in MultisplitPerm, behind an option, to measure before restructuring anything. Stacked on #78 (it uses
subgroupDigitMatch); review that first.What it does
new MultisplitPerm({ ..., ranking: "stable" }). The default stays"atomic", and its output and code paths are unchanged.wgslFunctions.wgStableRankis a new shared helper that ranks elements stably by digit across a workgroup (Ashkiani et al., TOPC 2017):subgroupDigitMatch), with one counter row per subgroup. Only the highest matching lane adds, so no atomic arrival order reaches the result.K * sgszconsecutive positions), so rank order is position order whatever the subgroup width.2^bitscounters per subgroup.wgStableRankinstead of workgroup atomics.slot, slot + M, …, in both hist and scatter. Otherwise a stable tile ranking still would not give a stable multisplit.wgStableRanktoo (it used atomics).Consequence: every group reaches the finish in index order, and each sub-bucket keeps that order. So the output is reproducible on every GPU without the sub-bucket sort or the overflow sort that
reproducible: trueneeds today.reference()models it: the same Fisher–Yates streams, with index order where today's model sorts. Stable mode defaults to groups of 2,048, since it has no sort cost that grows with group size.Testing
reference()bit for bit. The cases are keys; indices with several tiles per workgroup; three passes; the overflow path; Philox-7 pairs; and 2^20 (8-bit pass).u32mask) path on real hardware. The M1 Max run below covers it.Measure
examples/multisplitperm_bench_node.mjscompares, after a 200 ms warm-up on each variant:Decision this informs
reproducible: truecould use stable ranking. L3 would then cost about what L2 does. Reproducible outputs would change, and the paper's references would need regenerating.Generated by Claude Code