Repository navigation
feat(cuda-device): add SharedPtr, a CTA-shared pointer typed addrspace(3) - #1341
Closed
lucifer1004 wants to merge 1 commit into
Closed
lucifer1004 wants to merge 1 commit into
lucifer1004 wants to merge 1 commit into
Conversation
…e(3) `SharedPtr<T>` is a raw pointer into the issuing CTA's shared memory that carries its address space in its type. It wraps a `*mut SharedSlot<T>`, which the importer types as an `addrspace(3)` pointer, as it already does for pointers to `SharedArray` and `Barrier`, and the importer lowers `SharedPtr` itself to that pointer. Parameters, returns, locals, struct fields and generic code of type `SharedPtr<T>` are therefore CTA-shared pointers by type, across calls to non-inlined helpers, with no dataflow inference. - Constructors: `SharedArray::shared_ptr(&raw mut S)` and `DynamicSharedArray::shared_ptr()` / `shared_ptr_at(bytes)` keep the allocation's shared address; `unsafe SharedPtr::from_raw` is the one explicit locality assertion. - `add` / `offset` / `byte_add` / `cast` keep the type; `as_ptr` widens to a generic pointer; `addr_u32` gives the 32-bit `.shared::cta` address for the `_shared_u32` forms. - The importer drops projections onto `SharedPtr`'s field, which are the identity for this scalar-lowered newtype, so a `SharedPtr` nested in another place is read as a pointer value. - A kernel entry cannot take a `SharedPtr`: the exporter already rejects `addrspace(3)` kernel parameters. - `shared_memory_helper` runs its probe a second time through a non-inlined generic helper that takes the `SharedPtr` in a struct; `verify-code-shape.sh` checks the helper's `ptr addrspace(3)` parameter and that no PTX converts a generic address to shared. Refs NVIDIA#1337, NVIDIA#1238. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Zihua Wu <13583761+lucifer1004@users.noreply.github.com>
This was referenced Sep 26, 2026
Collaborator
|
Landed through #1336 at 8bb24a4: your commit is the first one on that branch, unchanged and with your sign-off, plus the review follow-ups ( |
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.
Part of #1337; groundwork for #1238.
What this adds
SharedPtr<T>: a raw pointer into the issuing CTA's shared memory (.shared::cta) that carries its address space in its type.A
*mut Tin device code is a generic pointer. Once it is passed to a helper, nothing tells the compiler that it points into this CTA's shared memory; helpers are compiled as separate functions whatever their inline attribute.SharedPtr<T>lowers to anaddrspace(3)pointer wherever it goes: parameters and returns of non-inlined helpers, struct fields, generic functions and closures. Instructions that take it can use their.shared::ctaforms without converting a generic address, which is what #1238 needs for TMA on SM12x (see #1337).SharedArray::shared_ptr(&raw mut S)DynamicSharedArray::<T>::shared_ptr()/shared_ptr_at(bytes)get()/offset(bytes)unsafe SharedPtr::from_raw(p)__cvta_generic_to_sharedor CuTemake_smem_ptradd,offset,byte_add,castas_ptr()*mut T, for loads, stores and raw-pointer APIsaddr_u32().shared::ctaaddress, for the_shared_u32forms (#1236)Only a mutable form is provided: shared memory is written through the same pointers it is read through, and
as_ptr()gives a*mut Tthat coerces to*const Twhere an API wants one.How it works
SharedPtr<T>is#[repr(transparent)] struct SharedPtr<T> { ptr: *mut SharedSlot<T> }, with a#[doc(hidden)]#[repr(transparent)] SharedSlot<T>(T)pointee.SharedSlot<T>as anaddrspace(3)pointer toT, as it already does for pointers toSharedArrayandBarrier. It lowersSharedPtr<T>itself to that same pointer, as a scalar-lowered newtype likeThreadIndex. Construction therefore reuses the existing newtype aggregate path, and reading the field is the existing scalarextract_field.Field(0)projection on aSharedPtrplace is the identity, so the place walkers drop it. Without that, aSharedPtrnested in another place, such asregion.base.ptrafter rustc inlinescast, was read as the address of an aggregate.#[inline(always)]Rust: casts between*mut SharedSlot<_>stay inaddrspace(3),as_ptris the3 → 0addrspacecastthat&raw mut S as *mut Talready emits, andfrom_rawis the0 → 3cast.SharedPtrcannot be a kernel parameter. The exporter already rejectsaddrspace(3)entry parameters, and it does so forSharedPtrtoo:kernel ... parameter 0 is a pointer into shared memory (address space 3) ....map_shared_rank, which may name another CTA's shared memory, are notSharedPtrs.SharedArray::as_ptr/as_mut_ptrandDynamicSharedArray::getstill return generic pointers.Tests
shared_memory_helperruns its probe a second time throughSharedPtr, with no features required:Region<T> { base: SharedPtr<T>, offset };byte_add/cast;PASS shared-ptr: 9 launches, 36 CTA data/barrier checks.The raw
*mut u8helpers of the same example still fail MIR verification, as the README documents.The new
verify-code-shape.shchecks thatshared_ptr_probetakesptr addrspace(3)in the emitted LLVM IR, and that no PTX converts a generic address to a shared one (cvta.to.shared).In a scratch kernel, not committed, the remaining API also computed correct values on the GPU:
SharedArray::shared_ptr,from_rawand a negativeoffset;SharedPtrpassed to a closure;addr_u32differences.A
SharedPtrkernel parameter fails to compile with the exporter diagnostic above.Validation
All runs used an RTX PRO 6000 (sm_120) with the CUDA 13.3 toolkit.
just fmt-check,clippy,testandtest-cudapass (3963 and 1505 tests).just doc-checkpasses.just check-guardspasses every script except two, whose results could not be obtained here:cargo deny --locked checkstops at the advisory-database lock (NFS do not support locking).cargo deny check bans licenses sourcespasses for all three workspaces.check-example-license-policy.shhits the same lock.This PR adds no dependency and changes no lockfile.
Full
scripts/smoketest.sh: 233/234 pass, the same asmain. The one failure,sparse_mma_fp8, also fails onmain.shared_memory_helperpasses on both backends: LLVM NVPTX, and libNVVM with--emit-nvvm-ir --arch=sm_120. Each backend runs both the direct and theSharedPtrprobe. On libNVVM, the helper is stilldefine i64 @…shared_ptr_probe…(ptr addrspace(3) %v0, i64 %v1).Follow-ups tracked in #1337: #1336 moves
cp_async_bulk_tensor_*_g2s_ctaontoSharedPtr<u8>on top of this PR;SharedPtrforms for cp.async, ldmatrix/stmatrix and the tcgen05/wgmma descriptors; a cluster-shared counterpart frommap_shared_rank.🤖 Generated with Claude Code