[CuTeDSL] reduce example: replace inline PTX with cute.arch.store_async_dsmem - #3593
Open
zkyue wants to merge 3 commits into
Open
[CuTeDSL] reduce example: replace inline PTX with cute.arch.store_async_dsmem#3593zkyue wants to merge 3 commits into
zkyue wants to merge 3 commits into
Conversation
…inline PTX The Blackwell reduce example carried two hand-rolled helpers, `set_block_rank` and `store_shared_remote`, that emitted `mapa.shared::cluster` and `st.async.shared::cluster...f32` through `llvm.inline_asm` because those instructions were not exposed by the DSL when the example was written. `cute.arch` now provides `map_dsmem_ptr` (mapa) and `store_async_dsmem` (mapa + st.async with mbarrier::complete_tx::bytes), so the example can call the built-in directly: * drop `set_block_rank` / `store_shared_remote` and the `llvm` / `T` imports * `cluster_reduce` calls `cute.arch.store_async_dsmem(ptr, val.bitcast(Int32), mbar_ptr, peer_cta_rank=lane_idx)`; the built-in stores raw 32-bit words, hence the Float32 -> Int32 bitcast (no data conversion, same bytes land in the peer CTA) * refresh the module docstring / section comment accordingly Behaviour is unchanged: same transaction-byte accounting, same mbarrier protocol, one fewer place that hard-codes PTX in an example.
…educe Doc-only follow-up spotted in review: * the module docstring and the cluster_reduce example told callers to `mbarrier_init(mbar, thread_count)`; the protocol (and the RMSNorm caller) uses an arrival count of 1 since a single elected thread does the arrive_and_expect_tx * "only lane 0's value is used for stores" was stale: lanes 0..cluster_n-1 each store to one CTA * "peer CTA" -> "every CTA in the cluster" (the local rank is included)
…ce + cluster sync The cluster_reduce usage example initialised the mbarrier from every thread and skipped the init fence / cluster barrier that the real caller (RMSNorm) performs before any remote DSMEM store. Mirror the caller.
Contributor
Author
|
Tested on B200 with |
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.
Summary
The Blackwell
reduce.pyexample still hand-rolls two cluster helpers,set_block_rankandstore_shared_remote, that emitmapa.shared::clusterandst.async.shared::cluster.mbarrier::complete_tx::bytes.f32viallvm.inline_asm. That was necessary when the example landed (#2917), butcute.archnow exposes the same functionality as built-ins:cute.arch.map_dsmem_ptr—mapa.shared::cluster, returns a dsmemPointercute.arch.store_async_dsmem— maps destination + mbarrier to the peer CTA and issuesst.asyncwithmbarrier::complete_tx::bytesThis PR removes the inline PTX and calls the built-in directly from
cluster_reduce.Changes
set_block_rank/store_shared_remoteand thecutlass._mlir.dialects.llvm/Timports.cluster_reducenow callscute.arch.store_async_dsmem(elem_pointer(...), val.bitcast(Int32), mbar_ptr, peer_cta_rank=lane_idx).The built-in stores raw
b32words, so theFloat32is reinterpreted asInt32withNumeric.bitcast(anarith.bitcast, no data conversion). The transaction-byte accounting (num_warps * cluster_n * 4) and the mbarrier protocol are unchanged.Net:
1 file changed, 18 insertions(+), 96 deletions(-), and the example no longer contains any inline PTX.Notes
store_async_dsmemwas added in the v4.8 dev update, so the example now requires a 4.8+nvidia-cutlass-dslfor thecluster_n > 1path.map_dsmem_ptr(4.6+) is not called directly becausestore_async_dsmemperforms bothmapatranslations internally; keepingset_block_rankas a wrapper around it would have been dead code.elem_pointeris untouched.Testing
Run on a B200 (sm_100a, CUDA 13.3) with
nvidia-cutlass-dsl==4.8.0.dev0:This includes
TestRMSNormClusterPath::test_cluster_path_correctness[32768]and[65536], which exercise exactly the changed path (cluster_n > 1in the RMSNorm example, which importsrow_reducefrom this file). All non-cluster RMSNorm tests pass as well.PTX of the cluster kernel (
CUTE_DSL_KEEP=ptx) shows the same instruction sequence as the removed inline asm, with the built-in emitting a.b32store instead of.f32(same bytes moved):Also checked statically against
cute.arch.store_async_dsmem's contract: both pointers are SMEMPointers fromSmemAllocator, the value is a singleInt32(4-byte alignment requirement satisfied by theFloat32buffer), andpeer_cta_rankis the lane index as before.The two follow-up commits are doc-only (mbarrier arrival count is 1, lanes
0..cluster_n-1each store, the usage example now mirrors the caller's init-fence / cluster-sync sequence).