Repository navigation
feat(cuda-device): support u64 and i64 in cooperative_groups reductions and scans - #1576
Open
praveenperera wants to merge 1 commit into
Open
praveenperera wants to merge 1 commit into
praveenperera wants to merge 1 commit into
Conversation
warp_reduce, warp_scan, block_reduce and block_scan rejected u64: neither u64: WarpShuffle nor Sum: ReduceOp<u64> existed, and a downstream crate cannot add the WarpShuffle impl for a primitive. Add u64 shuffles to WarpCollective, with default bodies built from the u32 methods so outside implementations keep compiling. The built-in groups override them with warp::shuffle_*_u64_sync under their own masks and tile rules. Implement WarpShuffle for u64 and i64, ReduceOp<u64> for all six combiners, and ReduceOp<i64> for Sum, Min and Max, matching i32. The coop_groups_u64 example checks every op against a CPU reference across tile sizes 1 to 32, partial block warps, sparse coalesced groups and values that only the high word decides. Closes NVIDIA#1497 Signed-off-by: Praveen Perera <me@praveenperera.com>
praveenperera
marked this pull request as ready for review
October 20, 2026 18:51
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.
Closes #1497.
The problem
warp_reduce,warp_scan,block_reduce, andblock_scanaccept onlyu32,i32, andf32. Au64call such aswarp_reduce::<u64, Sum, 32>(tile, value)fails withE0277for bothu64: WarpShuffleandSum: ReduceOp<u64>. A downstream crate can't add the missingWarpShuffleimpl for a primitive type, so the only workaround is a newtype with its own shuffles and combiners.WarpShuffleis generic overWarpCollective, and that trait had no 64-bit shuffle. So the low-levelwarp::shuffle_*_u64_syncfunctions from #278 were not reachable with a group's mask and tile-boundary rules.The fix
All library changes are in
cuda-device/src/cooperative_groups.rs:WarpCollectivegainsshfl_u64,shfl_xor_u64,shfl_down_u64, andshfl_up_u64, matching the existing_f32set.WarpTile<N>,CoalescedThreads, and the private partial-warp prefix group implement them with the same masks and source-lane rules as their 32-bit shuffles, on top ofwarp::shuffle_*_u64_sync. Each one is a single inline-PTX block with twoshfl.sync.*.b32, one per half.CoalescedThreadsgets a privaterank_to_lanehelper, shared by theu32,f32, andu64index shuffles, in place of three copies of the same loop.WarpShuffleis implemented foru64and fori64.i64casts throughu64, the same wayi32casts throughu32.ReduceOp<u64>is implemented forSum(wrapping),Min,Max,BitAnd,BitOr, andBitXor.ReduceOp<i64>is implemented forSum,Min, andMax.I added
i64because it falls out of the same pattern: oneWarpShuffleimpl that casts throughu64, and the three combinersi32already has. Bitwise ops stay unsigned-only, as they are for 32 bits.f64would work the same way, but I left it out of this PR.The new trait methods have default bodies that move the two halves through the existing
u32methods, so aWarpCollectiveimpl outside this crate still compiles and gets workingu64shuffles. The built-in groups override all four with the single-block form.redux.synchas no 64-bit form, so the 64-bit types always use the shuffle path. The new impls sit after thef32ones and use the default for theHAS_FULL_WARP_FORMitem that #1305 adds, so they don't overlap its hunks. The book's supported-features table now lists the new types.Testing
On an RTX 5090 (sm_120), CUDA 13.2, driver 595.99:
coop_groups_u64compares every result with a CPU reference:WarpTile<N>for N = 1, 2, 4, 8, 16, and 32, in blocks of 128 threads, so each launch has several warps and, below 32 lanes, several tiles per warp. Each tile size runs the 18 reductions and inclusive scans (sixu64ops and threei64ops) and the fouru64group shuffles. The shuffle offsets include ones that reach past the tile, where the caller must get its own value back. 28,672 results per tile size.block_reduceandblock_scanat 14 block sizes: 1, 7, 31, 32, 33, 45, 64, 100, 255, 256, 257, 640, 1000, and 1024 threads, three blocks each. Nine of the sizes leave a partial final warp. 202,230 results in total.CoalescedThreadsu64shuffles on eight groups, from the full warp to a single lane, including sparse ones such as0x8010_0089.u64shuffles on 8- and 32-lane groups through a wrapper that implements only the requiredWarpCollectivemethods, as a group from another crate would. This exercises the default bodies.total(&WarpTile<32>, u64)function written as in the issue.MinandMax, low words whoseSumcarries into the high word, values just belowu64::MAXwhoseSumwraps, theu64andi64extremes, and all-u64::MAXand all-negative blocks.u64ori64shuffle;Mincomparing low words only;Sumwithout the carry between halves; 32-bitBitAndandMinidentities;0as thei64Maxidentity; eachWarpTileshuffle ignoring the tile boundary or base lane;CoalescedThreadstreating a rank as a lane or skipping the member check; and, in the default bodies, a high half taken from the low half, shuffled the wrong way or read from the wrong rank, or reassembled with its halves swapped. The one it missed makes the partial-warp prefix use a full 32-lane mask. That is undefined behavior, but the 5090 returns correct results, and memcheck and synccheck report nothing. The existingu32path has the same gap, andpartial_warp_reducedocuments the same behavior.compute-sanitizer2026.1.1: memcheck 0 errors and synccheck 0 errors on the final code. Racecheck reported 0 hazards on the code before review, whose block kernels are unchanged.u64exchange inwarp_totalis one{ mov.b64 {lo, hi}; shfl.sync.bfly.b32 lo; shfl.sync.bfly.b32 hi; mov.b64 }block followed byadd.s64. That is five blocks and tenshfl.sync.bfly.b32for a full warp, with no local memory. Before I added the kernels for the default bodies, which use two separateu32shuffles by design, all 638 shuffle sites in the example module were that same two-shuffle block (308up, 291bfly, 29down, 10idx), and the module used no local memory.just checkpasses, along with the new example'scargo clippy --all-targets -D warnings,cargo fmt --check, andscripts/sync-example-locks.sh --check. Before review,scripts/smoketest.shpassed 241/241 in both GPU and--compile-onlymodes, and 235/241 in--full-debug,coop_groups_u64included. The six full-debug failures fail the same way on unmodifiedmain: constant_memory_simple, iket_trace, packed_aggregate_abi, partial_warp_reduce, warp_sums, and wgmma_mma_bf16. After the review changes (default bodies and docs), the 14 cooperative-groups, warp, reduce, scan and shuffle examples pass in GPU and--compile-onlymodes.