CuTe Python DSL Reference
Execution Model
CuTe Python DSL is the Python surface for NVIDIA's CuTe layout algebra. Unlike cuTile's block-level abstraction, CuTe DSL exposes explicit thread/warp/warpgroup control, TMA pipelines, barrier choreography, and shared memory management.
Two-Level Host/Device Pattern
Every CuTe DSL kernel has two functions:
@cute.jit host function — runs on CPU, sets up TMA descriptors, computes grid, allocates shared memory, launches the kernel
@cute.kernel device function — runs on GPU, contains the actual computation
import cutlass
import cutlass.cute as cute
@cute.kernel
def my_kernel(tiled_mma: cute.TiledMma, ...):
tidx, _, _ = cute.arch.thread_idx()
bidx, bidy, _ = cute.arch.block_idx()
# ... GPU code
@cute.jit
def host_fn(a: cute.Tensor, b: cute.Tensor, c: cute.Tensor):
# Setup TMA descriptors, compute grid, allocate SMEM
my_kernel(...).launch(grid=grid_shape, block=block_shape, smem=smem_bytes)
Compilation Pipeline
Three-stage JIT compilation:
- Pre-Staging: Python AST rewriting
- Meta-Stage: Python interpreter executes meta-programs (compile-time constants resolved)
- Object-Stage: Compiler backend generates PTX → SASS
JIT artifacts are cached automatically. Control with CUTE_DSL_CACHE_DIR and CUTE_DSL_DISABLE_FILE_CACHING.
Key Difference from cuTile
| Aspect |
cuTile |
CuTe DSL |
| Abstraction level |
Block-level (no thread identity) |
Thread/warp/warpgroup level |
| TMA |
Implicit (allow_tma=True) |
Explicit descriptor setup in host |
| Shared memory |
Compiler-managed |
Explicit allocation and layout |
| Synchronization |
None exposed |
Barriers, arrive/wait, named barriers |
| Pipeline |
None exposed |
Explicit multi-stage async pipelines |
| MMA |
ct.mma(A, B, C) on tiles |
cute.gemm(tiled_mma, d, a, b, c) on partitioned fragments |
| Compilation |
cuTile bytecode → MLIR |
CuTe DSL JIT → PTX → SASS |
Core API Table
Decorators and Compilation
| API |
Purpose |
Key params |
@cute.kernel |
Device kernel decorator |
function name must match module filename |
@cute.jit |
Host JIT function decorator |
— |
kernel(...).launch(grid, block, smem, cluster) |
Launch kernel |
grid=(x,y,z), block=(threads,1,1), smem=bytes, cluster=(cx,cy,cz) |
cute.compile(fn, *args, options="...") |
Ahead-of-time compile |
"opt-level=3", "keep-ptx", etc. |
Thread/Block/Grid Indexing
| API |
Purpose |
cute.arch.thread_idx() |
Returns (tidx, tidy, tidz) |
cute.arch.block_idx() |
Returns (bidx, bidy, bidz) |
cute.arch.block_dim() |
Block dimensions |
cute.arch.grid_dim() |
Grid dimensions |
cute.arch.warp_idx() |
Warp index within block |
cute.arch.block_idx_in_cluster() |
Block index within cluster (Hopper+) |
Layout and Tensor Construction
| API |
Purpose |
Notes |
cute.make_layout(shape, stride) |
Create layout |
Core abstraction: maps coordinates → indices |
cute.make_ordered_layout(shape, order) |
Create with stride order |
e.g., order=(1,0) for column-major |
cute.make_identity_layout(shape) |
Identity layout |
For predication |
cute.make_tensor(ptr, layout) |
Create tensor view |
Pairs pointer + layout |
cute.make_fragment(layout, dtype) |
Allocate register tensor |
For accumulators |
cute.make_fragment_like(src, dtype) |
Register tensor matching source |
— |
cute.make_ptr(dtype, addr, memspace) |
Tagged pointer |
cute.AddressSpace.smem/gmem |
cute.from_dlpack(tensor) |
Convert PyTorch/JAX tensor |
Returns cute.Tensor with .mark_layout_dynamic() |
Layout Algebra
| API |
Purpose |
cute.size(t, mode=None) |
Total size or modal size |
cute.shape(t) |
Get shape tuple |
cute.stride(t) |
Get stride tuple |
cute.rank(t) |
Number of modes |
cute.local_tile(tensor, tiler, coord, proj) |
Extract block's tile |
cute.logical_divide(tensor, divisor) |
Divide into tile + rest |
cute.composition(layout1, layout2) |
Compose layouts |
cute.complement(layout) |
Complement layout |
cute.coalesce(layout) |
Simplify layout |
cute.flatten(t) |
Flatten tensor/layout |
cute.group_modes(layout, start, end) |
Group modes together |
cute.tile_to_shape(tile, shape) |
Tile to target shape |
cute.ceil_div(a, b) |
Ceiling division |
MMA Operations
| API |
Purpose |
Notes |
cute.make_tiled_mma(op) |
Create tiled MMA from operation |
e.g., tcgen05.MmaF16BF16Op(...) |
tiled_mma.get_slice(thread_idx) |
Get thread's partition |
Returns ThrMma |
thr_mma.partition_A(tensor) |
Partition A operand |
Thread-level view |
thr_mma.partition_B(tensor) |
Partition B operand |
Thread-level view |
thr_mma.partition_C(tensor) |
Partition C operand |
Thread-level view |
tiled_mma.partition_shape_C(shape) |
Shape of C partition |
For fragment allocation |
tiled_mma.make_fragment_A(tensor) |
Make A fragment |
Register allocation |
tiled_mma.make_fragment_B(tensor) |
Make B fragment |
Register allocation |
tiled_mma.make_fragment_C(shape) |
Make C fragment |
Register allocation |
cute.gemm(tiled_mma, d, a, b, c) |
Execute MMA: d = a @ b + c |
Dispatches to hardware MMA |
Copy and TMA Operations
| API |
Purpose |
Notes |
cute.make_tiled_copy(atom) |
Create tiled copy |
For bulk data movement |
cute.copy(atom, src, dst, **kw) |
Execute copy |
tma_bar_ptr=, mcast_mask= |
cute.basic_copy(src, dst) |
Element-wise copy |
No atom needed |
cute.prefetch(atom, src) |
Prefetch TMA descriptor |
— |
cute.nvgpu.make_tiled_tma_atom_A(op, tensor, smem_layout, tile, mma) |
Create TMA atom for A |
Host-side only |
cute.nvgpu.make_tiled_tma_atom_B(op, tensor, smem_layout, tile, mma) |
Create TMA atom for B |
Host-side only |
Shared Memory
| API |
Purpose |
cutlass.utils.SmemAllocator() |
Create SMEM allocator |
smem.allocate_tensor(dtype, layout, align, swizzle) |
Allocate tensor in SMEM |
smem.allocate(struct_type) |
Allocate struct in SMEM |
Tensor Memory (SM100 only)
| API |
Purpose |
cutlass.utils.TmemAllocator(...) |
Create TMEM allocator |
tmem.allocate(num_cols) |
Allocate columns |
tmem.wait_for_alloc() |
Wait for allocation |
tmem.retrieve_ptr(dtype) |
Get pointer |
tmem.free(ptr) |
Free memory |
Synchronization
| API |
Purpose |
cute.arch.mbar.init(barrier_ptr, count) |
Initialize barrier |
cute.arch.mbar.arrive(barrier_ptr) |
Arrive at barrier |
cute.arch.mbar.wait(barrier_ptr, phase) |
Wait at barrier |
cute.arch.mbar.arrive_and_expect_tx(barrier_ptr, bytes) |
Arrive with expected TX bytes |
cute.arch.mbar.try_wait(barrier_ptr, phase) |
Non-blocking wait |
| Pipeline classes (see references) |
Multi-stage async pipelines |
Math (Element-wise on TensorSSA)
| API |
Purpose |
API |
Purpose |
cute.exp(x) |
e^x |
cute.exp2(x) |
2^x |
cute.log(x) |
ln(x) |
cute.log2(x) |
log2(x) |
cute.sqrt(x) |
sqrt |
cute.rsqrt(x) |
1/sqrt(x) |
cute.sin(x) |
sin |
cute.cos(x) |
cos |
cute.tanh(x) |
tanh |
cute.erf(x) |
erf |
All math functions accept fastmath=True for approximate hardware intrinsics.
Tensor Operations
| API |
Purpose |
cute.full(shape, val, dtype) |
Fill with value |
cute.zeros_like(tensor) |
Zero tensor matching shape |
cute.where(cond, x, y) |
Conditional select |
cute.any_(tensor) |
Logical any |
cute.all_(tensor) |
Logical all |
Debugging
| API |
Purpose |
cute.printf(fmt, ...) |
Device-side printf |
cute.print_tensor(tensor) |
Print tensor contents |
print(...) |
Compile-time print (meta-stage only) |
Key Constraints
@cute.kernel function name must match module filename — same rule as cuTile
TMA descriptors are host-side only — create in @cute.jit, pass to @cute.kernel
Register budget: 255 max/thread — validate with docs/devices/ specs
SMEM limits vary by device and SM version — SM100 (B200/B300): 228 KB/SM, 227 KB/block opt-in; SM120 (RTX 5090): 96 KB
Pipeline stages consume SMEM — each stage needs its own buffer; validate total
Barrier sync errors are silent — cause incorrect results, not crashes; always test with --check
Cluster dimensions must be compatible with grid — cluster shape must evenly divide grid
print() is compile-time only — use cute.printf() for device-side output
No early-exit breaks in loops — use predication instead
32-bit layout algebra — shapes/strides limited to 32-bit integers
Architecture support: Ampere (SM80) and above; SM100 (B200/B300) for full features including tcgen05 and TMEM
Architecture-specific kernels: Some kernels target a specific SM version (e.g., tcgen05 MMA ops require SM100, not just "Blackwell"). The "Blackwell" marketing name spans multiple SM versions with different instruction sets:
- SM100 (B200, B300) — datacenter GPUs, supports
tcgen05 MMA, TMEM, full cluster features
- SM120 (GeForce RTX 5090, RTX 5080) — consumer Blackwell, uses
sm_120a, does not support tcgen05 ops
Always check the device before running, compiling, or profiling: nvidia-smi --query-gpu=name --format=csv,noheader. Then match against the kernel's target SM version — the GPU name alone is not sufficient; you must know which SM version it maps to. If the SM version does not match, skip the run/profiling step rather than attempting execution that will fail or produce misleading results.
Control Flow
| Construct |
Behavior |
Notes |
for i in range(N) |
Unrolled if N is static |
Standard Python range |
for i in cutlass.range(N) |
Runtime loop |
Generates MLIR loop |
for i in cutlass.range_constexpr(N) |
Compile-time unroll |
N must be static |
if cutlass.const_expr(cond) |
Compile-time branch |
Eliminated at compile time |
if cond |
Runtime branch |
Both branches must type-check |
Blackwell Datacenter MMA Operations (tcgen05) — SM100 only
SM100 required. tcgen05 ops are available on B200/B300 (SM100) only. They are not available on consumer Blackwell GPUs like RTX 5090 (SM120/sm_120a).
from cutlass.cute.nvgpu import tcgen05
# Create MMA operation for SM100 (B200/B300) tensor cores
op = tcgen05.MmaF16BF16Op(
dtype=cutlass.Float16, # Input type
acc_dtype=cutlass.Float32, # Accumulator type
shape=(128, 128, 64), # M x N x K tile shape
cta_group=tcgen05.CtaGroup.ONE, # ONE or TWO CTAs
)
tiled_mma = cute.make_tiled_mma(op)
| Operation |
Input types |
Shapes |
MmaF16BF16Op |
FP16/BF16 → FP32 |
Various M×N×K |
MmaF8F6F4Op |
FP8/FP6/FP4 → FP32 |
Narrow precision |
| Block-scaled variants |
With scale factors |
See examples |
Common Patterns
GEMM with TMA Pipeline (Simplified)
@cute.kernel
def gemm_kernel(tiled_mma, tma_a, tma_b, smem_a, smem_b, gmem_c, ...):
tidx, _, _ = cute.arch.thread_idx()
bidx, bidy, _ = cute.arch.block_idx()
# Get thread's MMA partition
thr_mma = tiled_mma.get_slice(tidx)
# Allocate accumulator in registers
acc = tiled_mma.partition_shape_C(tile_shape)
tCrC = cute.make_fragment(acc, cutlass.Float32)
# K-loop with TMA pipeline
for k_tile in range(num_k_tiles):
# TMA copy: global → shared (async)
cute.copy(tma_a, gA_tile, sA_tile, tma_bar_ptr=barrier)
cute.copy(tma_b, gB_tile, sB_tile, tma_bar_ptr=barrier)
# Wait for TMA to complete
cute.arch.mbar.wait(barrier, phase)
# Partition shared memory for this thread
tCsA = thr_mma.partition_A(sA)
tCsB = thr_mma.partition_B(sB)
# MMA: accumulate into registers
cute.gemm(tiled_mma, tCrC, tCsA, tCsB, tCrC)
# Epilogue: write back to global memory
cute.basic_copy(tCrC, gC_partition)
Warpgroup Specialization (Producer/Consumer)
warp_idx = cute.arch.warp_idx()
is_producer = warp_idx < num_producer_warps
if is_producer:
# Issue TMA copies for upcoming pipeline stages
for stage in range(num_stages):
cute.copy(tma_atom, src, dst, tma_bar_ptr=barriers[stage])
cute.arch.mbar.arrive_and_expect_tx(barriers[stage], bytes_per_stage)
else:
# Consume data from shared memory, execute MMA
for stage in range(num_stages):
cute.arch.mbar.wait(barriers[stage], phase)
cute.gemm(tiled_mma, acc, sA_stage, sB_stage, acc)
Persistent Kernel Loop
@cute.kernel
def persistent_kernel(tiled_mma, num_tiles, ...):
bidx, _, _ = cute.arch.block_idx()
num_blocks = cute.arch.grid_dim()[0]
tile_id = bidx
while tile_id < num_tiles:
# Process tile
# ... TMA copy, MMA, epilogue ...
tile_id += num_blocks
Detailed References
- Architecture operations (thread indexing, TMA, MMA atoms, barriers, SMEM/TMEM): See references/architecture-ops.md
- Official documentation index: See references/docs-index.md
- Example kernels: See the
/learn-cute-dsl skill for a categorized example source index
1---2name: cute-dsl-ref3description: CuTe Python DSL API reference and implementation patterns for NVIDIA GPU kernel programming. Provides execution model, core API table, key constraints, common patterns, and documentation index. Use when: (1) writing or modifying CuTe DSL kernel code, (2) looking up CuTe DSL API syntax, (3) implementing attention/GEMM/MLA patterns in CuTe DSL, (4) understanding CuTe DSL execution model and compilation pipeline, (5) checking what CuTe DSL can and cannot do.4---56# CuTe Python DSL Reference78## Execution Model910CuTe Python DSL is the Python surface for NVIDIA's CuTe layout algebra. Unlike cuTile's block-level abstraction, CuTe DSL exposes **explicit thread/warp/warpgroup control**, TMA pipelines, barrier choreography, and shared memory management.1112### Two-Level Host/Device Pattern1314Every CuTe DSL kernel has two functions:15161. **`@cute.jit` host function** — runs on CPU, sets up TMA descriptors, computes grid, allocates shared memory, launches the kernel172. **`@cute.kernel` device function** — runs on GPU, contains the actual computation1819```python20import cutlass21import cutlass.cute as cute2223@cute.kernel24def my_kernel(tiled_mma: cute.TiledMma, ...):25 tidx, _, _ = cute.arch.thread_idx()26 bidx, bidy, _ = cute.arch.block_idx()27 # ... GPU code2829@cute.jit30def host_fn(a: cute.Tensor, b: cute.Tensor, c: cute.Tensor):31 # Setup TMA descriptors, compute grid, allocate SMEM32 my_kernel(...).launch(grid=grid_shape, block=block_shape, smem=smem_bytes)33```3435### Compilation Pipeline3637Three-stage JIT compilation:381. **Pre-Staging**: Python AST rewriting392. **Meta-Stage**: Python interpreter executes meta-programs (compile-time constants resolved)403. **Object-Stage**: Compiler backend generates PTX → SASS4142JIT artifacts are cached automatically. Control with `CUTE_DSL_CACHE_DIR` and `CUTE_DSL_DISABLE_FILE_CACHING`.4344### Key Difference from cuTile4546| Aspect | cuTile | CuTe DSL |47|--------|--------|----------|48| Abstraction level | Block-level (no thread identity) | Thread/warp/warpgroup level |49| TMA | Implicit (`allow_tma=True`) | Explicit descriptor setup in host |50| Shared memory | Compiler-managed | Explicit allocation and layout |51| Synchronization | None exposed | Barriers, arrive/wait, named barriers |52| Pipeline | None exposed | Explicit multi-stage async pipelines |53| MMA | `ct.mma(A, B, C)` on tiles | `cute.gemm(tiled_mma, d, a, b, c)` on partitioned fragments |54| Compilation | cuTile bytecode → MLIR | CuTe DSL JIT → PTX → SASS |5556---5758## Core API Table5960### Decorators and Compilation6162| API | Purpose | Key params |63|-----|---------|-----------|64| `@cute.kernel` | Device kernel decorator | function name must match module filename |65| `@cute.jit` | Host JIT function decorator | — |66| `kernel(...).launch(grid, block, smem, cluster)` | Launch kernel | `grid=(x,y,z)`, `block=(threads,1,1)`, `smem=bytes`, `cluster=(cx,cy,cz)` |67| `cute.compile(fn, *args, options="...")` | Ahead-of-time compile | `"opt-level=3"`, `"keep-ptx"`, etc. |6869### Thread/Block/Grid Indexing7071| API | Purpose |72|-----|---------|73| `cute.arch.thread_idx()` | Returns `(tidx, tidy, tidz)` |74| `cute.arch.block_idx()` | Returns `(bidx, bidy, bidz)` |75| `cute.arch.block_dim()` | Block dimensions |76| `cute.arch.grid_dim()` | Grid dimensions |77| `cute.arch.warp_idx()` | Warp index within block |78| `cute.arch.block_idx_in_cluster()` | Block index within cluster (Hopper+) |7980### Layout and Tensor Construction8182| API | Purpose | Notes |83|-----|---------|-------|84| `cute.make_layout(shape, stride)` | Create layout | Core abstraction: maps coordinates → indices |85| `cute.make_ordered_layout(shape, order)` | Create with stride order | e.g., `order=(1,0)` for column-major |86| `cute.make_identity_layout(shape)` | Identity layout | For predication |87| `cute.make_tensor(ptr, layout)` | Create tensor view | Pairs pointer + layout |88| `cute.make_fragment(layout, dtype)` | Allocate register tensor | For accumulators |89| `cute.make_fragment_like(src, dtype)` | Register tensor matching source | — |90| `cute.make_ptr(dtype, addr, memspace)` | Tagged pointer | `cute.AddressSpace.smem/gmem` |91| `cute.from_dlpack(tensor)` | Convert PyTorch/JAX tensor | Returns `cute.Tensor` with `.mark_layout_dynamic()` |9293### Layout Algebra9495| API | Purpose |96|-----|---------|97| `cute.size(t, mode=None)` | Total size or modal size |98| `cute.shape(t)` | Get shape tuple |99| `cute.stride(t)` | Get stride tuple |100| `cute.rank(t)` | Number of modes |101| `cute.local_tile(tensor, tiler, coord, proj)` | Extract block's tile |102| `cute.logical_divide(tensor, divisor)` | Divide into tile + rest |103| `cute.composition(layout1, layout2)` | Compose layouts |104| `cute.complement(layout)` | Complement layout |105| `cute.coalesce(layout)` | Simplify layout |106| `cute.flatten(t)` | Flatten tensor/layout |107| `cute.group_modes(layout, start, end)` | Group modes together |108| `cute.tile_to_shape(tile, shape)` | Tile to target shape |109| `cute.ceil_div(a, b)` | Ceiling division |110111### MMA Operations112113| API | Purpose | Notes |114|-----|---------|-------|115| `cute.make_tiled_mma(op)` | Create tiled MMA from operation | e.g., `tcgen05.MmaF16BF16Op(...)` |116| `tiled_mma.get_slice(thread_idx)` | Get thread's partition | Returns `ThrMma` |117| `thr_mma.partition_A(tensor)` | Partition A operand | Thread-level view |118| `thr_mma.partition_B(tensor)` | Partition B operand | Thread-level view |119| `thr_mma.partition_C(tensor)` | Partition C operand | Thread-level view |120| `tiled_mma.partition_shape_C(shape)` | Shape of C partition | For fragment allocation |121| `tiled_mma.make_fragment_A(tensor)` | Make A fragment | Register allocation |122| `tiled_mma.make_fragment_B(tensor)` | Make B fragment | Register allocation |123| `tiled_mma.make_fragment_C(shape)` | Make C fragment | Register allocation |124| `cute.gemm(tiled_mma, d, a, b, c)` | Execute MMA: d = a @ b + c | Dispatches to hardware MMA |125126### Copy and TMA Operations127128| API | Purpose | Notes |129|-----|---------|-------|130| `cute.make_tiled_copy(atom)` | Create tiled copy | For bulk data movement |131| `cute.copy(atom, src, dst, **kw)` | Execute copy | `tma_bar_ptr=`, `mcast_mask=` |132| `cute.basic_copy(src, dst)` | Element-wise copy | No atom needed |133| `cute.prefetch(atom, src)` | Prefetch TMA descriptor | — |134| `cute.nvgpu.make_tiled_tma_atom_A(op, tensor, smem_layout, tile, mma)` | Create TMA atom for A | Host-side only |135| `cute.nvgpu.make_tiled_tma_atom_B(op, tensor, smem_layout, tile, mma)` | Create TMA atom for B | Host-side only |136137### Shared Memory138139| API | Purpose |140|-----|---------|141| `cutlass.utils.SmemAllocator()` | Create SMEM allocator |142| `smem.allocate_tensor(dtype, layout, align, swizzle)` | Allocate tensor in SMEM |143| `smem.allocate(struct_type)` | Allocate struct in SMEM |144145### Tensor Memory (SM100 only)146147| API | Purpose |148|-----|---------|149| `cutlass.utils.TmemAllocator(...)` | Create TMEM allocator |150| `tmem.allocate(num_cols)` | Allocate columns |151| `tmem.wait_for_alloc()` | Wait for allocation |152| `tmem.retrieve_ptr(dtype)` | Get pointer |153| `tmem.free(ptr)` | Free memory |154155### Synchronization156157| API | Purpose |158|-----|---------|159| `cute.arch.mbar.init(barrier_ptr, count)` | Initialize barrier |160| `cute.arch.mbar.arrive(barrier_ptr)` | Arrive at barrier |161| `cute.arch.mbar.wait(barrier_ptr, phase)` | Wait at barrier |162| `cute.arch.mbar.arrive_and_expect_tx(barrier_ptr, bytes)` | Arrive with expected TX bytes |163| `cute.arch.mbar.try_wait(barrier_ptr, phase)` | Non-blocking wait |164| Pipeline classes (see references) | Multi-stage async pipelines |165166### Math (Element-wise on TensorSSA)167168| API | Purpose | API | Purpose |169|-----|---------|-----|---------|170| `cute.exp(x)` | e^x | `cute.exp2(x)` | 2^x |171| `cute.log(x)` | ln(x) | `cute.log2(x)` | log2(x) |172| `cute.sqrt(x)` | sqrt | `cute.rsqrt(x)` | 1/sqrt(x) |173| `cute.sin(x)` | sin | `cute.cos(x)` | cos |174| `cute.tanh(x)` | tanh | `cute.erf(x)` | erf |175176All math functions accept `fastmath=True` for approximate hardware intrinsics.177178### Tensor Operations179180| API | Purpose |181|-----|---------|182| `cute.full(shape, val, dtype)` | Fill with value |183| `cute.zeros_like(tensor)` | Zero tensor matching shape |184| `cute.where(cond, x, y)` | Conditional select |185| `cute.any_(tensor)` | Logical any |186| `cute.all_(tensor)` | Logical all |187188### Debugging189190| API | Purpose |191|-----|---------|192| `cute.printf(fmt, ...)` | Device-side printf |193| `cute.print_tensor(tensor)` | Print tensor contents |194| `print(...)` | Compile-time print (meta-stage only) |195196---197198## Key Constraints1992001. **`@cute.kernel` function name must match module filename** — same rule as cuTile2012. **TMA descriptors are host-side only** — create in `@cute.jit`, pass to `@cute.kernel`2023. **Register budget: 255 max/thread** — validate with `docs/devices/` specs2034. **SMEM limits vary by device and SM version** — SM100 (B200/B300): 228 KB/SM, 227 KB/block opt-in; SM120 (RTX 5090): 96 KB2045. **Pipeline stages consume SMEM** — each stage needs its own buffer; validate total2056. **Barrier sync errors are silent** — cause incorrect results, not crashes; always test with `--check`2067. **Cluster dimensions must be compatible with grid** — cluster shape must evenly divide grid2078. **`print()` is compile-time only** — use `cute.printf()` for device-side output2089. **No early-exit breaks in loops** — use predication instead20910. **32-bit layout algebra** — shapes/strides limited to 32-bit integers21011. **Architecture support**: Ampere (SM80) and above; SM100 (B200/B300) for full features including `tcgen05` and TMEM21112. **Architecture-specific kernels**: Some kernels target a specific SM version (e.g., `tcgen05` MMA ops require **SM100**, not just "Blackwell"). The "Blackwell" marketing name spans multiple SM versions with different instruction sets:212 - **SM100** (B200, B300) — datacenter GPUs, supports `tcgen05` MMA, TMEM, full cluster features213 - **SM120** (GeForce RTX 5090, RTX 5080) — consumer Blackwell, uses `sm_120a`, does **not** support `tcgen05` ops214215 Always check the device before running, compiling, or profiling: `nvidia-smi --query-gpu=name --format=csv,noheader`. Then match against the kernel's target SM version — the GPU name alone is not sufficient; you must know which SM version it maps to. If the SM version does not match, **skip the run/profiling step** rather than attempting execution that will fail or produce misleading results.216217## Control Flow218219| Construct | Behavior | Notes |220|-----------|----------|-------|221| `for i in range(N)` | Unrolled if N is static | Standard Python range |222| `for i in cutlass.range(N)` | Runtime loop | Generates MLIR loop |223| `for i in cutlass.range_constexpr(N)` | Compile-time unroll | N must be static |224| `if cutlass.const_expr(cond)` | Compile-time branch | Eliminated at compile time |225| `if cond` | Runtime branch | Both branches must type-check |226227---228229## Blackwell Datacenter MMA Operations (tcgen05) — SM100 only230231> **SM100 required.** `tcgen05` ops are available on B200/B300 (SM100) only. They are **not** available on consumer Blackwell GPUs like RTX 5090 (SM120/`sm_120a`).232233```python234from cutlass.cute.nvgpu import tcgen05235236# Create MMA operation for SM100 (B200/B300) tensor cores237op = tcgen05.MmaF16BF16Op(238 dtype=cutlass.Float16, # Input type239 acc_dtype=cutlass.Float32, # Accumulator type240 shape=(128, 128, 64), # M x N x K tile shape241 cta_group=tcgen05.CtaGroup.ONE, # ONE or TWO CTAs242)243244tiled_mma = cute.make_tiled_mma(op)245```246247| Operation | Input types | Shapes |248|-----------|-------------|--------|249| `MmaF16BF16Op` | FP16/BF16 → FP32 | Various M×N×K |250| `MmaF8F6F4Op` | FP8/FP6/FP4 → FP32 | Narrow precision |251| Block-scaled variants | With scale factors | See examples |252253---254255## Common Patterns256257### GEMM with TMA Pipeline (Simplified)258259```python260@cute.kernel261def gemm_kernel(tiled_mma, tma_a, tma_b, smem_a, smem_b, gmem_c, ...):262 tidx, _, _ = cute.arch.thread_idx()263 bidx, bidy, _ = cute.arch.block_idx()264265 # Get thread's MMA partition266 thr_mma = tiled_mma.get_slice(tidx)267268 # Allocate accumulator in registers269 acc = tiled_mma.partition_shape_C(tile_shape)270 tCrC = cute.make_fragment(acc, cutlass.Float32)271272 # K-loop with TMA pipeline273 for k_tile in range(num_k_tiles):274 # TMA copy: global → shared (async)275 cute.copy(tma_a, gA_tile, sA_tile, tma_bar_ptr=barrier)276 cute.copy(tma_b, gB_tile, sB_tile, tma_bar_ptr=barrier)277278 # Wait for TMA to complete279 cute.arch.mbar.wait(barrier, phase)280281 # Partition shared memory for this thread282 tCsA = thr_mma.partition_A(sA)283 tCsB = thr_mma.partition_B(sB)284285 # MMA: accumulate into registers286 cute.gemm(tiled_mma, tCrC, tCsA, tCsB, tCrC)287288 # Epilogue: write back to global memory289 cute.basic_copy(tCrC, gC_partition)290```291292### Warpgroup Specialization (Producer/Consumer)293294```python295warp_idx = cute.arch.warp_idx()296is_producer = warp_idx < num_producer_warps297298if is_producer:299 # Issue TMA copies for upcoming pipeline stages300 for stage in range(num_stages):301 cute.copy(tma_atom, src, dst, tma_bar_ptr=barriers[stage])302 cute.arch.mbar.arrive_and_expect_tx(barriers[stage], bytes_per_stage)303else:304 # Consume data from shared memory, execute MMA305 for stage in range(num_stages):306 cute.arch.mbar.wait(barriers[stage], phase)307 cute.gemm(tiled_mma, acc, sA_stage, sB_stage, acc)308```309310### Persistent Kernel Loop311312```python313@cute.kernel314def persistent_kernel(tiled_mma, num_tiles, ...):315 bidx, _, _ = cute.arch.block_idx()316 num_blocks = cute.arch.grid_dim()[0]317318 tile_id = bidx319 while tile_id < num_tiles:320 # Process tile321 # ... TMA copy, MMA, epilogue ...322 tile_id += num_blocks323```324325---326327## Detailed References328329- **Architecture operations** (thread indexing, TMA, MMA atoms, barriers, SMEM/TMEM): See [references/architecture-ops.md](references/architecture-ops.md)330- **Official documentation index**: See [references/docs-index.md](references/docs-index.md)331- **Example kernels**: See the `/learn-cute-dsl` skill for a categorized example source index