Repository navigation
Conversation
A load-balanced reduction of each tile of a CSR-style array, after Osama, Porumbescu and Owens (PPoPP 2023): the schedule is separate from the work, which the caller writes as JS functions that return WGSL (atom, emit), Gridwise's stand-in for the paper's C++ lambdas. Merge-path combines split tiles with a segmented scan in the workgroup and a fixup kernel between workgroups, so each tile is emitted once with its whole value (no float atomics needed). SpMV is a SegmentedReduce. Tests (segred) and misc/benchmark_spmv.mjs (uniform, R-MAT, dense-row and Matrix Market). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
…rries Combining the workgroups' carries is itself a segmented reduce: atoms are the carries, tiles are the workgroups (each holding the run of carries in the tile it ends, found by a binary search), and emit adds the run into the workgroup's head value. It runs merge-path too, recursively until one workgroup suffices, and binds only its own carry buffers; a last kernel emits the heads. Replaces the walk-back fixup, which took half the time on a matrix with one row of 2^25 nonzeros. Adds tileStart (a function in place of the offsets buffer) and wgsl options; itemsPerThread defaults to 4, the fastest on an M1 Max, a V100 and an A100. Test: three levels of fixup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
The fixup's emit added the run's carries into the head value in place, so a repeated kernel (benchmark()'s trials) added them again: wrong results on the M1 Max benchmark. It now writes to a third slot; every kernel can be repeated. Tests with kernels repeated (trials 2 and 3), which fail without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
…sults The fixup levels' kernels were labeled like the main kernel, so the benchmark's fixup time left them out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Each schedule (ThreadMapped, WorkgroupMapped, MergePath, in src/schedules.mjs) writes its kernels and says what runs; SegmentedReduce holds only the work (binop, tileStart, atom, emit) and helpers schedules use (kernel, allocate, child, run). Schedules call the work through binop/IDENTITY/tileStartOf/atomValue/emitTile and the sr uniform. A schedule is given as an instance or by a name in SegmentedReduce.schedules; adding one changes nothing in SegmentedReduce, as a test with a schedule defined in the test file shows. MergePath's fixup is a child SegmentedReduce. Adds WorkgroupMapped (the paper's block-mapped) to the tests and the benchmark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
This branch has not been deployed
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.
A test of the load-balancing programming model of Osama, Porumbescu and Owens (PPoPP 2023) on WebGPU: a load-balanced reduction of each tile (segment) of a CSR-style array, with the schedule separate from the work.
SegmentedReduce(src/segmentedreduce.mjs) holds the work, which the caller gives as JS functions that return WGSL:atom: (atom, tile) => expression,emit: (tile, value) => statement, and optionallytileStart: (t) => expressionin place of an offsets buffer. These are Gridwise's stand-in for the paper's C++ lambdas.src/schedules.mjs) are classes that write the kernels and call the work throughbinop,tileStartOf,atomValueandemitTile.SegmentedReduceknows no schedule by more than its name, and a test defines one outside the library.ThreadMapped: one invocation per tile.WorkgroupMapped: one workgroup per tile (the paper's block-mapped).MergePath(Merrill and Garland): tiles + atoms path steps split evenly. Split tiles are combined by a segmented scan within the workgroup, and between workgroups by a fixup that is itself aSegmentedReduce: its atoms are the workgroups' carries, its tiles are the workgroups. It runs merge-path, recursively until one workgroup suffices, so a tile spanning any number of workgroups costs nothing extra. Every tile is emitted once, with its whole value, with no float atomics.SpMV(src/spmv.mjs): y = Ax (CSR, f32) as aSegmentedReduce.segred, 32): u32 add, i32 max and SpMV against the CPU; all three schedules and an outside one; 1, 7 and 16 items per invocation; three levels of fixup; kernels repeated in place (trials); uniform, power-law, skewed, one-tile and all-empty shapes; sizes changing between executes.misc/benchmark_spmv.mjs: the schedules on uniform, R-MAT and dense-row matrices or Matrix Market files, checked against the CPU.docs/segmented-reduce.md: the model, the schedules, writing a schedule, a worked example of the fixup, measurements on an M1 Max, a V100 and an A100 (merge-path at 2^22: 2× thread-mapped on uniform, 8–15× on R-MAT, 1,500–2,800× with one dense row, at the same GFLOP/s on all three).https://claude.ai/code/session_015kfNC6id65zEHzuAAH4jtJ
Generated by Claude Code