CUDA Authoring and Support APIs#
CUDA helpers#
The CUDA backend installs the Tx.cuda namespace when it is loaded:
from tvm.script import tirx as Tx
Tx.cuda.cta_sync()
leader = Tx.cuda.elect_sync()
These helpers cover operations that need multiple instructions, C/C++ expressions, descriptor packing, compiler annotations, or other behavior that is not represented as one table-driven PTX instruction. For a single supported PTX instruction, use Direct PTX Instructions.
The current Tx.cuda surface includes:
Category |
Helpers |
|---|---|
Synchronization and participation |
|
Barriers and memory ordering |
|
Reductions |
|
Descriptors and addresses |
|
Loads, calls, and diagnostics |
|
Numeric conversion and packed math |
|
Instrumentation and compatibility |
|
NVSHMEM namespace#
The same backend installs Tx.nvshmem for my_pe, n_pes,
signal_op, wait_until, quiet, fence, and barrier_all.
Its getmem_nbi, putmem_nbi, and putmem_signal_nbi operations also
provide .warp and .block variants.
CUDA language utilities#
tvm.backend.cuda.lang provides reusable objects for hand-written CUDA TIRx
kernels, including schedulers, pipelines, roles, barriers, descriptors, and
memory pools.
- class tvm.backend.cuda.lang.BaseTileScheduler(*args, **kwargs)#
Base class for tile schedulers with common state and macros.
- class tvm.backend.cuda.lang.ClusterPersistentScheduler2D(prefix, num_m_tiles, num_n_tiles, num_clusters, l2_group_size=8, cluster_m=1, cluster_n=1, serpentine=False)#
Persistent two-dimensional tile scheduler with group-major or serpentine traversal.
initselects the first tile for a cluster,next_tileornext_tile_strideadvances it, andvalidreports whether the currentm_idx/n_idxis in range.
- class tvm.backend.cuda.lang.FlashAttentionLPTScheduler(*args, **kwargs)#
LPT scheduler with L2 swizzle for causal flash attention.
Processes high-work Q blocks (with more KV blocks to attend to) first using Longest Processing Time (LPT) scheduling. Also applies L2 cache swizzle for better cache locality across batch*head dimensions.
The LPT aspect comes from reversing m_block order: lower Q blocks have more KV blocks to process due to causal masking, so processing them first balances load.
The scheduler is only applied to non-persistent kernels.
L2 Swizzle: Groups consecutive batch*head indices together for L2 locality.
- Parameters:
prefix (str) – Prefix for TIR variable names
num_batches (int) – Number of batches
num_heads (int) – Number of KV heads
num_m_blocks (int) – Number of Q blocks (M dimension tiles)
num_ctas (int) – Number of CTAs (should equal total_tasks for causal)
l2_swizzle (int) – L2 swizzle factor for cache locality
- valid()#
Check if there are more tiles to process.
- class tvm.backend.cuda.lang.FlashAttentionLinearScheduler(prefix, num_batches, num_heads, num_m_blocks, num_ctas)#
Linear persistent scheduler over
(batch, head, m_block)tasks.initstarts from a CTA index,next_tileadvances bynum_ctas, andvalidreports whether work remains.
- class tvm.backend.cuda.lang.GroupMajor3D(*args, **kwargs)#
3D grouped-row scheduler (M,N,K) with tail handling on M.
- class tvm.backend.cuda.lang.IndexedTripleTileScheduler(*args, **kwargs)#
Scheduler that maps linear_idx to (b_idx, h_idx, q_idx) via index lists.
- class tvm.backend.cuda.lang.MBarrier(*args, **kwargs)#
Mbarrier wrapper with regular
mbarrier.arrive.- Parameters:
pool (SMEMPool) – Shared memory pool allocator.
depth (int) – Number of barrier slots (one per pipeline stage).
phase_offset (int) – XORed into the phase bit on every
wait/arrive.leader (Expr, optional) –
Boolean predicate selecting the single thread that runs
mbarrier.init. Defaults toT.cuda.thread_rank() == 0– thread 0 of the enclosing CTA, which always picks exactly one thread regardless of which scope_id vars the caller declared. Override only when you want a different CTA-local thread to do the init.Note: the default deliberately avoids
T.warp_id()/T.lane_id(). Those introduce deferredcta->warp/warp->threadScopeIdDefs that the verifier cannot pin down unless the kernel header declares the full warp/lane chain (e.g. a single-CTA DSMEM kernel that only declaresthread_id). It also avoids the synccheck false-deadlock on kernels that declare a second warp-scope id. The generated CUDA is equivalent.
- remote_view(rank)#
Create a view of this barrier mapped to another CTA’s shared memory.
The returned view retains the local barrier and target CTA so
arriveemits the cluster form. Its mapped buffer remains available throughptr_tofor operations that consume a remote shared-memory pointer.initandwaitare local-only and reject remote views.
- class tvm.backend.cuda.lang.Pipeline(*args, **kwargs)#
A full/empty mbarrier pair for a software-pipelined data flow.
Pass barrier-type tags and
Pipelineconstructs andinits the barriers itself. Tags:"tma"(TMABar),"tcgen05"(TCGen05Bar),"mbar"(MBarrier). The barrier type and arrival count of each event stay explicit at the call site – e.g.Pipeline(pool, n, full="tma", empty="tcgen05", init_empty=NUM_CONSUMER).Both signals are required: a
Pipelineis a pair. For a one-way event (a pure “X happened” signal with no slot to recycle) use a bare barrier (TMABar/TCGen05Bar/MBarrier) directly – it has no empty side.- Parameters:
pool (SMEMPool) – Shared memory pool allocator.
stages (int) – Number of pipeline stages (barrier slots).
full (str) – Barrier-type tag for the full / empty signal (see above).
empty (str) – Barrier-type tag for the full / empty signal (see above).
init_full (int) – Expected arrival count for the full / empty barrier.
init_empty (int) – Expected arrival count for the full / empty barrier.
empty_phase_offset (int) – XORed into the empty barrier’s phase bit on every wait / arrive.
leader (Expr, optional) – Propagated to both barriers; defaults to thread 0 of the CTA.
- class tvm.backend.cuda.lang.PipelineState(*args, **kwargs)#
Tracks stage and phase for a software-pipelined ring buffer.
This class does not know anything about full/empty barriers. Use it when the kernel manually waits/signals barriers, or when the stage/phase drives a ring not wrapped in a
Pipeline.
- class tvm.backend.cuda.lang.RankAwareGroupMajorTileScheduler(*args, **kwargs)#
Group-major scheduler that applies a rank-aware remapping (remote rows first). Kept as a thin adapter because it depends on NVSHMEM rank at device-side.
- class tvm.backend.cuda.lang.SMEMPool(*args, **kwargs)#
Bump allocator over a contiguous shared memory region.
- Parameters:
ptr (Var or None, optional) – If omitted, an
alloc_buffer([0], "uint8", scope="shared.dyn")is created automatically andcommit()must be called after all allocations to emit the size annotation. If aVaris provided, the caller manages the backing buffer andcommit()is a no-op.
- alloc_tcgen05_mma_AB(shape, dtype='float16', swizzle_mode='auto', align=1024)#
Allocate MMA-compatible shared memory with an inferred swizzle layout.
- class tvm.backend.cuda.lang.SmemDescriptor(*args, **kwargs)#
Encoded once via
init(), reused viaadd_16B_offset().- make_lo_uniform()#
Broadcast the lower 32 bits to all warp lanes via
__shfl_sync.
- class tvm.backend.cuda.lang.TCGen05Bar(*args, **kwargs)#
Barrier signaled by
tcgen05commit.The caller is responsible for ensuring only one thread issues the commit, e.g. by wrapping the call in
if T.cuda.elect_sync():or by passingpred=T.cuda.elect_sync(). Thepredform emits the predicated instruction (@p tcgen05.commit) instead of a branch and lets one elected leader predicate be shared across several commits.
- class tvm.backend.cuda.lang.TMABar(*args, **kwargs)#
Barrier signaled by TMA (mbarrier.arrive.expect_tx).
When
tx_countis None, falls back to a remote mbarrier.arrive (matching MBarrier.arrive defaults).
- class tvm.backend.cuda.lang.TMEMPool(*args, **kwargs)#
Bump allocator over TMEM columns.
- alloc_sf(shape, dtype, *, sf_per_mma, sf_reuse=1)#
Allocate a tcgen05 block-scaled SF TMEM buffer with an inferred layout.
shapelast two dims are(rows, SF_K * sf_reuse)(the last dim is what gemm dispatch iterates over). Whenshapehas 3 dims, the first is treated as a pipe-depth outer.
- alloc_tcgen05_mma_A(shape, dtype='bfloat16', *, M, cta_group, ws=False, sparse=False, cols=None)#
Allocate a TMEM A operand (A-in-TMEM); layout resolved from MMA instruction params.
Mis the PTX tcgen05.mma instruction M (256/128/ 64), NOT per-CTA rows. Seelocaldoc/claude_plan.txtS3a.
- alloc_tcgen05_mma_D(shape, dtype='float32', *, M, cta_group, ws=False, sparse=False, group=None, cols=None)#
Allocate a TMEM D/C accumulator operand.
M= PTX instruction M.group=(s,2,n)gives a flat (m,N) buffer a grouped column layout.
- alloc_tcgen05_mma_C(shape, dtype='float32', *, M, cta_group, ws=False, sparse=False, group=None, cols=None)#
Allocate a TMEM D/C accumulator operand.
M= PTX instruction M.group=(s,2,n)gives a flat (m,N) buffer a grouped column layout.
- TMEMPool.alloc(shape, dtype='float32', *, layout=None, cols=None)#
Allocate a tensor-memory buffer from the pool.
layoutsupplies an explicitTileLayout; without it, two-dimensional shapes use the default dense layout.colsoverrides the inferred tensor-memory column count. Datapath-specific accumulators can instead usealloc_tcgen05_mma_D(...)/alloc_tcgen05_mma_C(...).
- class tvm.backend.cuda.lang.WarpRole(warp_id_var, warp_id_val, regs=None, increase=False)#
A warp-level role that guards a block of code by warp_id comparison with optional register budget.
Generates:
if <warp_id_var> == <warp_id_val>: # if regs specified: T.ptx[f"setmaxnreg.{'inc' if <increase> else 'dec'}.sync.aligned.u32"](<regs>) <user code>
The
ifguard narrows the active set to the single warp; individual tile-primitive calls inside<user code>carry their own exec scope via a scope-namespace prefix (e.g.Tx.warp.copy(...)).- Parameters:
warp_id_var (Var) – The warp_id variable (from
T.warp_id(...)).warp_id_val (int) – Which warp index this role corresponds to.
regs (int, optional) – Register budget (passed to
T.ptx.setmaxnreg). If None, no setmaxnreg is emitted.increase (bool) – Direction for
setmaxnreg(default False = decrease).
- class tvm.backend.cuda.lang.WarpgroupRole(wg_id_var, wg_id_val, regs=None, increase=False)#
A warpgroup-level role that guards by wg_id comparison, with optional register budget.
Generates (single wg_id):
if <wg_id_var> == <wg_id_val>: # if regs specified: T.ptx[f"setmaxnreg.{'inc' if <increase> else 'dec'}.sync.aligned.u32"](<regs>) <user code>
Generates (range of wg_ids, e.g.
wg_id_val=(0, 2)):if 0 <= <wg_id_var> and <wg_id_var> < 2: T.ptx[f"setmaxnreg.{'inc' if <increase> else 'dec'}.sync.aligned.u32"](<regs>) <user code>
The
ifguard narrows the active set to the target warpgroup(s); individual tile-primitive calls inside<user code>carry their own exec scope via a scope-namespace prefix (e.g.Tx.wg.copy(...)).- Parameters:
IKET profiling#
NVIDIA IKET annotations and run-iket orchestration.
profile runs an explicit replayable command. run is intended for a
script’s __main__ block: the parent process asks run-iket to replay the
original script or python -m invocation, while the injected tracker and
capture processes execute the supplied callable and then exit.
- exception tvm.backend.cuda.iket.IketProfileError(message: str, *, returncode: int | None = None, command: Sequence[str] = (), output_tail: str = '', timeout: float | None = None)
An error while validating or running an official IKET profile.
- class tvm.backend.cuda.iket.IketProfileResult(output_dir: Path, postprocess: str, json_traces: tuple[Path, ...], perfetto_traces: tuple[Path, ...], html_reports: tuple[Path, ...], command: tuple[str, ...] = ())
Published artifacts from a successful official IKET profile.
- property trace_json: Path
Return the only JSON trace requested by this profile.
- property perfetto: Path
Return the only Perfetto trace requested by this profile.
- property html: Path
Return the only HTML report requested by this profile.
- property trace: Any
Return the JSON trace without imposing a schema wrapper.
- property launches: Any
Return
trace["launches"]without reshaping it.
- class tvm.backend.cuda.iket.IketProfiler(*args, **kwargs)
TIRx annotations compiled for NVIDIA’s official IKET runtime.
- compile(mod, target=None, *, tir_pipeline='tirx')
Compile official IKET metadata and NativeDump placeholders.
- tvm.backend.cuda.iket.profile(command: Sequence[str | PathLike[str]], *, output_dir: str | PathLike[str], profile_name: str = 'cutlass-4.6.0', postprocess: str = 'all', clobber: bool = False, cwd: str | PathLike[str] | None = None, env: Mapping[str, str | PathLike[str]] | None = None, max_ts_cnt_per_warp: int | None = None, keep: bool = False, timeout: float | None = 600.0) → IketProfileResult
Profile a replayable command with NVIDIA’s official
run-ikettool.
- tvm.backend.cuda.iket.run(main, *, output_dir: str | PathLike[str], profile_name: str = 'cutlass-4.6.0', postprocess: str = 'all', clobber: bool = False, cwd: str | PathLike[str] | None = None, env: Mapping[str, str | PathLike[str]] | None = None, max_ts_cnt_per_warp: int | None = None, keep: bool = False, timeout: float | None = 600.0) → IketProfileResult
Replay the active script under
run-iketand executemainin its passes.Module-level code executes once in the parent, tracker, and capture processes.
mainexecutes only in tracker and capture. Code followingrunexecutes only in the parent after a successful profile.
CUDA-specific transforms#
CUDA-specific TIRx transformations.
- tvm.backend.cuda.transforms.LowerIket()
Lower frontend-only NVIDIA IKET annotations.
This pass must run after
tvm.tirx.transform.SplitHostDeviceand beforetvm.tirx.transform.MakePackedAPI. It strips annotations for regular compilation and emits NVIDIA IKET metadata and NativeDump placeholders when the IRModule is explicitly IKET-enabled. Trace collection and postprocessing are owned by the externalrun-iketprocess.- Returns:
fpass – The result pass.
- Return type:
tvm.transform.Pass