Vendored from NVIDIA/TensorRT-LLM under Apache-2.0. Includes verify/benchmark scripts and extensive references. Pair with perf-nsight-compute-analysis. See LICENSE-Apache-2.0.txt.
CuTe DSL
CuTe DSL is a Python-based domain-specific language for GPU kernel development,
part of CUTLASS 4.x. It provides Python abstractions over CUTLASS C++ templates
with JIT compilation to optimized CUDA kernels via MLIR and ptxas.
When to Use
Triggers:
- Writing CUDA kernels in Python (element-wise, GEMM, custom ops)
- Optimizing GPU memory access patterns (vectorized loads, TMA, shared memory)
- Building tensor core (MMA) kernels for Ampere/Hopper/Blackwell
- Integrating custom GPU kernels with PyTorch or JAX
- Prototyping high-performance kernels without C++ metaprogramming
Symptoms (wrong tool otherwise):
- Need shared memory coordination or tensor core MMA → use CuTe DSL (not Triton for complex patterns)
- Need simple element-wise ops with no shared memory → CuTe DSL or Triton both work
- Need to call existing CUTLASS C++ kernels → use CUTLASS C++ APIs instead
- Need reductions, scans, or non-GEMM collective ops → consider CUB/Thrust
Keywords: cute, cutlass, cute.jit, cute.kernel, from_dlpack, zipped_divide,
TiledMMA, TiledCopy, TMA, WGMMA, tcgen05, pipeline, mbarrier
Requirements
| Requirement |
Detail |
| Platform |
Linux x86_64 only |
| Python |
3.10–3.13 |
| GPU |
NVIDIA Ampere+ (SM80, SM90, SM100) |
| CUDA Driver |
≥ 575.51.03 (Toolkit 12.9 compat) |
| Install |
pip install nvidia-cutlass-dsl |
| Optional |
apache-tvm-ffi, torch-c-dlpack-ext |
Workflows
Workflow 0: Starting from Examples (Recommended)
For any non-trivial kernel (GEMM, attention, pipelined, fused ops), start by
finding the most similar existing example to use as a starting point — study
its structure, then rework it for your use case. Do not copy examples verbatim;
they target specific dtypes, architectures, and problem shapes that likely differ.
Pick the closest example from the index below.
Prefer examples matching the target GPU architecture (check with
torch.cuda.get_device_capability()) when the operation is similar.
Fetch via web_fetch with base URL
https://raw.githubusercontent.com/NVIDIA/cutlass/main/examples/python/CuTeDSL
| Operation |
Arch |
Example path (append to base URL) |
| Element-wise add |
SM80 |
ampere/elementwise_add.py |
| Element-wise + autotune |
SM80 |
ampere/elementwise_add_autotune.py |
| Element-wise apply |
SM80 |
ampere/elementwise_apply.py |
| SGEMM (scalar) |
SM80 |
ampere/sgemm.py |
| Tensor-core GEMM |
SM80 |
ampere/tensorop_gemm.py |
| Flash Attention v2 |
SM80 |
ampere/flash_attention_v2.py |
| HSTU Attention |
SM80 |
ampere/hstu_attention.py |
| Shared memory allocator |
SM80 |
ampere/smem_allocator.py |
| CTA norm (LayerNorm) |
SM90 |
hopper/cta_norm.py |
| Dense GEMM |
SM90 |
hopper/dense_gemm.py |
| Dense GEMM persistent |
SM90 |
hopper/dense_gemm_persistent.py |
| Flash MHA |
SM90 |
hopper/fmha.py |
| Dense GEMM |
SM100 |
blackwell/dense_gemm.py |
| Dense GEMM persistent |
SM100 |
blackwell/dense_gemm_persistent.py |
| Dense GEMM + alpha/beta |
SM100 |
blackwell/dense_gemm_alpha_beta_persistent.py |
| RMSNorm |
SM100 |
blackwell/rmsnorm.py |
| Reduce |
SM100 |
blackwell/reduce.py |
| Flash MHA |
SM100 |
blackwell/fmha.py |
| Grouped GEMM |
SM100 |
blackwell/grouped_gemm.py |
| Mamba2 SSD |
SM100 |
blackwell/mamba2_ssd/ |
| GEMM tutorial (notebook) |
SM100 |
notebooks/tour_to_sol_gemm.ipynb |
Example: To fetch the Hopper dense GEMM:
web_fetch https://raw.githubusercontent.com/NVIDIA/cutlass/main/examples/python/CuTeDSL/hopper/dense_gemm.py
Read reference materials first — before diving into example code, read
the relevant references/ docs to understand the patterns and APIs:
- For GEMM:
references/patterns-gemm.md (3-level tiling, epilogue fusion,
cute.compile with mark_layout_dynamic, shared memory layouts)
- For reductions:
references/patterns-reduction.md (warp reductions,
cute.compile cache pattern)
- For element-wise:
references/patterns-elementwise.md (variations A–E)
- Always:
references/api-arch.md (available APIs, arch-specific caveats)
This gives you the conceptual foundation so you can rework the example
intelligently rather than trying to copy-paste complex pipelines.
Fetch and study the example source — read for structure, not to copy:
- Identify: decorators, tiling strategy, shared memory usage, mainloop flow
- Note which dtype/arch it targets (many examples are fp16/bf16-specific)
- Check if it uses APIs tied to a specific arch (TMA → SM90+, tcgen05 → SM100)
Rework for the user's workload (do not copy-paste):
- Change shapes, data types, tile sizes to match requirements
- Replace compute logic (epilogue, activation fusion) as needed
- If dtype differs (e.g., example is fp16, need fp32), expect vectorization
and layout changes — the scalar-loop patterns in
references/ may be a
better starting point than adapting a vectorized example
- Runtime wrapper must be lightweight:
kernel_fn() should only call
from_dlpack() + the compiled kernel. Never allocate intermediate tensors,
copy data, or re-compile per call — these belong in one-time setup
- Apply optimizations from this skill's reference docs
⛔ Blackwell/Hopper GEMM + extra tensors — STOP:
If the target GPU is SM90+ (Hopper/Blackwell) and the GEMM requires
extra tensors beyond A, B, C in the epilogue (e.g., bias vector, activation
inputs), do not attempt it. These examples use TMA descriptors for all
data movement — adding tensors requires modifying TMA descriptor setup,
which is prohibitively complex. Instead, tell the user this limitation and
suggest a two-kernel approach: run the GEMM kernel as-is, then apply
bias + activation in a separate element-wise kernel (Workflow 1).
Plain GEMM (just A×B→C with scalar alpha/beta) on Hopper/Blackwell is fine.
Validate and benchmark using companion scripts:
python scripts/verify_kernel.py kernel.py --rtol 1e-3 --atol 1e-3
python scripts/benchmark_kernel.py kernel.py
The kernel file must export kernel_fn, reference_fn, and get_inputs().
When to skip examples: Pure element-wise operations (Workflow 1) have
complete patterns in references/patterns-elementwise.md — no need to fetch
external examples.
Reduction kernels (softmax, layernorm, RMSNorm): Use
references/patterns-reduction.md which provides complete, proven patterns
for float32 reductions using scalar loops + butterfly shuffle + shared memory.
Workflow 1: Element-wise Kernel
For unary/binary/in-place operations that map inputs to outputs 1:1.
- Determine kernel structure: inputs/outputs count, tensor rank, target arch
- Select pattern from
references/patterns-elementwise.md (Variations A–E)
- Write kernel applying all four invariant principles:
- P1:
from_dlpack(tensor, assumed_align=16) for vector loads
- P2: Derive
vec_size from element_type.width
- P3:
cute.zipped_divide(mA, tiler) for coalesced access
- P4:
cutlass.dynamic_expr(thread_idx < total) for bounds
- Critical rules: No early return, no
a * 2 (use a + a), no cute.math.sigmoid
- Pre-compile with
cute.compile(): Always pre-compile the kernel once
using cute.compile() so that kernel_fn calls the compiled object, not
@cute.jit directly. Without pre-compilation, every call recompiles
(~20-50ms overhead). Use .mark_layout_dynamic() so a single compiled
kernel handles arbitrary input shapes without recompilation:# Compile once with dynamic layouts — works for any shape
fake_x = from_dlpack(torch.empty(1, 1, dtype=torch.float16, device="cuda"),
assumed_align=16).mark_layout_dynamic()
fake_out = from_dlpack(torch.empty(1, 1, dtype=torch.float16, device="cuda"),
assumed_align=16).mark_layout_dynamic()
compiled_kernel = cute.compile(host_fn, fake_x, fake_out)
def kernel_fn(x):
out = torch.empty_like(x)
compiled_kernel(from_dlpack(x, assumed_align=16).mark_layout_dynamic(),
from_dlpack(out, assumed_align=16).mark_layout_dynamic())
return out
- Verify correctness using companion script:
python scripts/verify_kernel.py kernel.py --rtol 1e-3 --atol 1e-3
The kernel file must export kernel_fn, reference_fn, and get_inputs().
- Benchmark using companion script:
python scripts/benchmark_kernel.py kernel.py
Workflow 2: GEMM Kernel
For matrix multiplication with tiling, shared memory, and tensor cores.
- Define problem: shapes (M, N, K), data types, target architecture
- Choose tiling: CTA tile (bM, bN, bK), pipeline stages, cluster shape
- Three-level partitioning (see
references/patterns-gemm.md):
- Level 1: CTA tiling with
local_tile()
- Level 2: Copy partitioning (global → shared) with
TiledCopy
- Level 3: Compute partitioning (shared → register) with
TiledMMA
- Shared memory: Use swizzled layouts (
make_smem_layout_atom) to avoid bank conflicts
- Mainloop: K-tile loop with copy → sync → MMA → sync
- Pipeline: Use
PipelineTmaAsync (Hopper) or PipelineTmaUmma (Blackwell).
⚠️ TMA-based pipelines manage data movement via TMA descriptors — adding
extra tensors (bias, activation inputs) to the epilogue requires modifying
descriptor setup, which is prohibitively complex. See the stop condition in
Workflow 0 step 4.
- Epilogue: Predicated store with alpha/beta scaling
- Pre-compile with
cute.compile(): Always pre-compile the GEMM kernel
so kernel_fn calls the compiled object, not @cute.jit directly.
Without pre-compilation, every call recompiles (~20-50ms overhead).
- Autotune: Search over tile sizes, cluster shapes, pipeline depths
Workflow 3: Framework Integration
For wrapping CuTe DSL kernels as PyTorch/JAX custom operators.
- Write kernel using Workflow 1 or 2
- Create wrapper: Accept
torch.Tensor, convert via from_dlpack, call host fn
- For production: Compile with TVM FFI for zero-overhead tensor passing:
compiled = cute.compile(host_fn, *fake_tensors, options="--enable-tvm-ffi")
compiled(torch_a, torch_b) # Direct torch.Tensor, no from_dlpack
- For deployment: Use AOT compilation → export to
.o → load at runtime
Workflow 4: Debugging & Profiling
- Set environment:
CUTE_DSL_PRINT_IR=1, CUTE_DSL_KEEP_PTX=1
- Use
cute.printf() for runtime values (not Python print)
- Inspect generated code:
compiled.__ptx__, compiled.__mlir__
- Profile: Enable
CUTE_DSL_LINEINFO=1, use Nsight Compute/Systems
- Debug memory: Run with
compute-sanitizer python script.py
Output Formats
A typical CuTe DSL kernel project:
kernel_dir/
kernel.py # @cute.kernel + @cute.jit functions
test_kernel.py # Correctness test vs PyTorch reference
bench_kernel.py # Benchmark with cute.compile() setup
Success indicators:
- Correctness test passes (
torch.testing.assert_close)
- Nsight shows vector loads (LDG.128/LDG.256), not scalar loads
- For GEMM: tensor core utilization > 80% in Nsight Compute
Companion Script Contract
Kernel files used with scripts/verify_kernel.py and scripts/benchmark_kernel.py
must export three names:
kernel_fn(*inputs) — the CuTe DSL kernel wrapper (calls cute.compile + runs kernel)
reference_fn(*inputs) — PyTorch reference implementation (same signature)
get_inputs() — returns a list of CUDA tensors for testing
# Example kernel.py contract
import torch
import cutlass.cute as cute
from cutlass.cute.runtime import from_dlpack
def kernel_fn(x):
out = torch.empty_like(x)
# ... call compiled cute kernel ...
return out
def reference_fn(x):
return torch.nn.functional.gelu(x)
def get_inputs():
return [torch.randn(1024, 512, dtype=torch.float16, device="cuda")]
Examples
Example: 2D Unary Element-wise (ReLU)
import torch, cutlass, cutlass.cute as cute
from cutlass.cute.runtime import from_dlpack
@cute.kernel
def relu_kernel(gA: cute.Tensor, gC: cute.Tensor):
tidx, _, _ = cute.arch.thread_idx()
bidx, _, _ = cute.arch.block_idx()
bdim, _, _ = cute.arch.block_dim()
idx = bidx * bdim + tidx
m, n = gA.shape[1]
total = m * n
if cutlass.dynamic_expr(idx < total):
a = gA[(None, (idx // n, idx % n))].load()
gC[(None, (idx // n, idx % n))] = cute.where(a > 0, a, 0)
@cute.jit
def relu_host(mA: cute.Tensor, mC: cute.Tensor):
vec = 16 // (mA.element_type.width // 8)
gA = cute.zipped_divide(mA, (1, vec))
gC = cute.zipped_divide(mC, (1, vec))
T = 256
N = cute.size(gA.shape[1])
relu_kernel(gA, gC).launch(grid=((N+T-1)//T,1,1), block=(T,1,1))
x = torch.randn(1024, 512, dtype=torch.float16, device="cuda")
out = torch.empty_like(x)
relu_host(from_dlpack(x, assumed_align=16), from_dlpack(out, assumed_align=16))
Error Handling
| Error |
Cause |
Fix |
MLIR function requires a Context |
Called @kernel from Python |
Launch via @cute.jit host function |
DSLAstPreprocessorError on return |
Early return in @kernel |
Use if cutlass.dynamic_expr(cond): |
| Type mismatch on store |
a * 2 promotes FP16→FP32 |
Use a + a or .to(cutlass.Float16) |
could not get source code |
Kernel in exec() context |
Write to file and import |
| Scalar loads in Nsight |
Missing alignment hint |
Add assumed_align=16 to from_dlpack |
Missing required argument |
Not all @jit params passed |
Pass ALL declared parameters |
AttributeError: sigmoid |
No cute.math.sigmoid |
Use 1.0/(1.0+cute.math.exp(-x)) |
See references/troubleshooting.md for the full error table and limitations.
Debugging rule: Never delete kernel.py during debugging. Use backup_file
to save a checkpoint, then edit_file to iterate. If stuck, revert_file to
restore the backup. A partially-working kernel is always better than no kernel.
Finding More Information
Tier 1: This File (SKILL.md)
Workflows above cover element-wise kernels, GEMM, framework integration, and
debugging. Search this file first for procedural questions.
Tier 2: references/ Directory
Grep for keywords across references/. Headers are grep-friendly.
| File |
Content |
concepts-architecture.md |
Core abstractions, terminology, compilation pipeline |
concepts-layouts.md |
Layout algebra: composition, complement, divide, swizzle |
concepts-tensors.md |
Tensor types, partitioning, tiling, predication |
concepts-mma.md |
MMA atoms, TiledMMA, per-architecture tensor core ops |
patterns-getting-started.md |
Installation, decorators, first kernel walkthrough |
patterns-elementwise.md |
Invariant principles, pattern variations, reference impl |
patterns-gemm.md |
3-level tiling, shared memory, pipelining, autotuning |
patterns-memory.md |
from_dlpack, TMA, cp.async, TMEM, copy atoms |
patterns-compilation.md |
Control flow, JIT caching, TVM FFI, AOT compilation |
patterns-pipeline.md |
Producer-consumer, pipeline classes, barriers, warp specialization |
api-core.md |
cute module: layouts, tensors, math, copy, gemm, printing |
api-arch.md |
cute.arch: thread indexing, sync, atomics, memory ops |
api-nvgpu.md |
cute.nvgpu: warp/warpgroup/cpasync/tcgen05 MMA and copy |
api-runtime-utils.md |
Runtime: from_dlpack, fake tensors, utils, schedulers |
troubleshooting.md |
Debugging, env vars, common errors, limitations, FAQ |
How to search: Grep for your keyword across references/. Read only the
file and section that Grep points to.
Tier 3: Original Documentation
If Tiers 1–2 don't answer, consult the source:
1---2name: kernel-cute-writing3description: Write GPU kernels using NVIDIA CuTe DSL (CUTLASS 4.x Python API) — NOT for Triton, CUDA C++, or conceptual-only questions. Covers element-wise kernels, GEMM patterns, reductions, memory hierarchy (global/shared/register/TMA), MMA tensor core ops, software pipelining, and framework integration. Use when implementing CUTLASS/CuTe kernels for inference GEMM, MoE, or attention in TRT-LLM / custom serving stacks.4license: Apache-2.05---67> **Vendored from [NVIDIA/TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM/tree/main/.claude/skills/kernel-cute-writing) under Apache-2.0.** Includes verify/benchmark scripts and extensive references. Pair with `perf-nsight-compute-analysis`. See `LICENSE-Apache-2.0.txt`.89# CuTe DSL1011CuTe DSL is a Python-based domain-specific language for GPU kernel development,12part of CUTLASS 4.x. It provides Python abstractions over CUTLASS C++ templates13with JIT compilation to optimized CUDA kernels via MLIR and ptxas.1415## When to Use1617**Triggers:**18- Writing CUDA kernels in Python (element-wise, GEMM, custom ops)19- Optimizing GPU memory access patterns (vectorized loads, TMA, shared memory)20- Building tensor core (MMA) kernels for Ampere/Hopper/Blackwell21- Integrating custom GPU kernels with PyTorch or JAX22- Prototyping high-performance kernels without C++ metaprogramming2324**Symptoms (wrong tool otherwise):**25- Need shared memory coordination or tensor core MMA → use CuTe DSL (not Triton for complex patterns)26- Need simple element-wise ops with no shared memory → CuTe DSL or Triton both work27- Need to call existing CUTLASS C++ kernels → use CUTLASS C++ APIs instead28- Need reductions, scans, or non-GEMM collective ops → consider CUB/Thrust2930**Keywords:** cute, cutlass, cute.jit, cute.kernel, from_dlpack, zipped_divide,31TiledMMA, TiledCopy, TMA, WGMMA, tcgen05, pipeline, mbarrier3233## Requirements3435| Requirement | Detail |36|-------------|--------|37| Platform | Linux x86_64 only |38| Python | 3.10–3.13 |39| GPU | NVIDIA Ampere+ (SM80, SM90, SM100) |40| CUDA Driver | ≥ 575.51.03 (Toolkit 12.9 compat) |41| Install | `pip install nvidia-cutlass-dsl` |42| Optional | `apache-tvm-ffi`, `torch-c-dlpack-ext` |4344## Workflows4546### Workflow 0: Starting from Examples (Recommended)4748For any non-trivial kernel (GEMM, attention, pipelined, fused ops), start by49finding the most similar existing example to use as a **starting point** — study50its structure, then rework it for your use case. Do not copy examples verbatim;51they target specific dtypes, architectures, and problem shapes that likely differ.52531. **Pick the closest example** from the index below.54 **Prefer examples matching the target GPU architecture** (check with55 `torch.cuda.get_device_capability()`) when the operation is similar.5657 Fetch via `web_fetch` with base URL58 `https://raw.githubusercontent.com/NVIDIA/cutlass/main/examples/python/CuTeDSL`5960 | Operation | Arch | Example path (append to base URL) |61 |-----------|------|-----------------------------------|62 | Element-wise add | SM80 | `ampere/elementwise_add.py` |63 | Element-wise + autotune | SM80 | `ampere/elementwise_add_autotune.py` |64 | Element-wise apply | SM80 | `ampere/elementwise_apply.py` |65 | SGEMM (scalar) | SM80 | `ampere/sgemm.py` |66 | Tensor-core GEMM | SM80 | `ampere/tensorop_gemm.py` |67 | Flash Attention v2 | SM80 | `ampere/flash_attention_v2.py` |68 | HSTU Attention | SM80 | `ampere/hstu_attention.py` |69 | Shared memory allocator | SM80 | `ampere/smem_allocator.py` |70 | CTA norm (LayerNorm) | SM90 | `hopper/cta_norm.py` |71 | Dense GEMM | SM90 | `hopper/dense_gemm.py` |72 | Dense GEMM persistent | SM90 | `hopper/dense_gemm_persistent.py` |73 | Flash MHA | SM90 | `hopper/fmha.py` |74 | Dense GEMM | SM100 | `blackwell/dense_gemm.py` |75 | Dense GEMM persistent | SM100 | `blackwell/dense_gemm_persistent.py` |76 | Dense GEMM + alpha/beta | SM100 | `blackwell/dense_gemm_alpha_beta_persistent.py` |77 | RMSNorm | SM100 | `blackwell/rmsnorm.py` |78 | Reduce | SM100 | `blackwell/reduce.py` |79 | Flash MHA | SM100 | `blackwell/fmha.py` |80 | Grouped GEMM | SM100 | `blackwell/grouped_gemm.py` |81 | Mamba2 SSD | SM100 | `blackwell/mamba2_ssd/` |82 | GEMM tutorial (notebook) | SM100 | `notebooks/tour_to_sol_gemm.ipynb` |8384 **Example:** To fetch the Hopper dense GEMM:85 ```bash86 web_fetch https://raw.githubusercontent.com/NVIDIA/cutlass/main/examples/python/CuTeDSL/hopper/dense_gemm.py87 ```88892. **Read reference materials first** — before diving into example code, read90 the relevant `references/` docs to understand the patterns and APIs:91 - For GEMM: `references/patterns-gemm.md` (3-level tiling, epilogue fusion,92 `cute.compile` with `mark_layout_dynamic`, shared memory layouts)93 - For reductions: `references/patterns-reduction.md` (warp reductions,94 `cute.compile` cache pattern)95 - For element-wise: `references/patterns-elementwise.md` (variations A–E)96 - Always: `references/api-arch.md` (available APIs, arch-specific caveats)9798 This gives you the conceptual foundation so you can rework the example99 intelligently rather than trying to copy-paste complex pipelines.1001013. **Fetch and study the example source** — read for structure, not to copy:102 - Identify: decorators, tiling strategy, shared memory usage, mainloop flow103 - Note which dtype/arch it targets (many examples are fp16/bf16-specific)104 - Check if it uses APIs tied to a specific arch (TMA → SM90+, tcgen05 → SM100)1051064. **Rework for the user's workload** (do not copy-paste):107 - Change shapes, data types, tile sizes to match requirements108 - Replace compute logic (epilogue, activation fusion) as needed109 - If dtype differs (e.g., example is fp16, need fp32), expect vectorization110 and layout changes — the scalar-loop patterns in `references/` may be a111 better starting point than adapting a vectorized example112 - **Runtime wrapper must be lightweight**: `kernel_fn()` should only call113 `from_dlpack()` + the compiled kernel. Never allocate intermediate tensors,114 copy data, or re-compile per call — these belong in one-time setup115 - Apply optimizations from this skill's reference docs116117 **⛔ Blackwell/Hopper GEMM + extra tensors — STOP:**118 If the target GPU is SM90+ (Hopper/Blackwell) **and** the GEMM requires119 extra tensors beyond A, B, C in the epilogue (e.g., bias vector, activation120 inputs), **do not attempt it**. These examples use TMA descriptors for all121 data movement — adding tensors requires modifying TMA descriptor setup,122 which is prohibitively complex. Instead, tell the user this limitation and123 suggest a **two-kernel approach**: run the GEMM kernel as-is, then apply124 bias + activation in a separate element-wise kernel (Workflow 1).125 Plain GEMM (just A×B→C with scalar alpha/beta) on Hopper/Blackwell is fine.1261275. **Validate and benchmark** using companion scripts:128 ```bash129 python scripts/verify_kernel.py kernel.py --rtol 1e-3 --atol 1e-3130 python scripts/benchmark_kernel.py kernel.py131 ```132 The kernel file must export `kernel_fn`, `reference_fn`, and `get_inputs()`.133134**When to skip examples:** Pure element-wise operations (Workflow 1) have135complete patterns in `references/patterns-elementwise.md` — no need to fetch136external examples.137138**Reduction kernels** (softmax, layernorm, RMSNorm): Use139`references/patterns-reduction.md` which provides complete, proven patterns140for float32 reductions using scalar loops + butterfly shuffle + shared memory.141142### Workflow 1: Element-wise Kernel143144For unary/binary/in-place operations that map inputs to outputs 1:1.1451461. **Determine kernel structure**: inputs/outputs count, tensor rank, target arch1472. **Select pattern** from `references/patterns-elementwise.md` (Variations A–E)1483. **Write kernel** applying all four invariant principles:149 - P1: `from_dlpack(tensor, assumed_align=16)` for vector loads150 - P2: Derive `vec_size` from `element_type.width`151 - P3: `cute.zipped_divide(mA, tiler)` for coalesced access152 - P4: `cutlass.dynamic_expr(thread_idx < total)` for bounds1534. **Critical rules**: No early return, no `a * 2` (use `a + a`), no `cute.math.sigmoid`1545. **Pre-compile with `cute.compile()`**: Always pre-compile the kernel once155 using `cute.compile()` so that `kernel_fn` calls the compiled object, not156 `@cute.jit` directly. Without pre-compilation, every call recompiles157 (~20-50ms overhead). Use `.mark_layout_dynamic()` so a single compiled158 kernel handles arbitrary input shapes without recompilation:159 ```python160 # Compile once with dynamic layouts — works for any shape161 fake_x = from_dlpack(torch.empty(1, 1, dtype=torch.float16, device="cuda"),162 assumed_align=16).mark_layout_dynamic()163 fake_out = from_dlpack(torch.empty(1, 1, dtype=torch.float16, device="cuda"),164 assumed_align=16).mark_layout_dynamic()165 compiled_kernel = cute.compile(host_fn, fake_x, fake_out)166167 def kernel_fn(x):168 out = torch.empty_like(x)169 compiled_kernel(from_dlpack(x, assumed_align=16).mark_layout_dynamic(),170 from_dlpack(out, assumed_align=16).mark_layout_dynamic())171 return out172 ```1736. **Verify correctness** using companion script:174 ```bash175 python scripts/verify_kernel.py kernel.py --rtol 1e-3 --atol 1e-3176 ```177 The kernel file must export `kernel_fn`, `reference_fn`, and `get_inputs()`.1787. **Benchmark** using companion script:179 ```bash180 python scripts/benchmark_kernel.py kernel.py181 ```182183### Workflow 2: GEMM Kernel184185For matrix multiplication with tiling, shared memory, and tensor cores.1861871. **Define problem**: shapes (M, N, K), data types, target architecture1882. **Choose tiling**: CTA tile (bM, bN, bK), pipeline stages, cluster shape1893. **Three-level partitioning** (see `references/patterns-gemm.md`):190 - Level 1: CTA tiling with `local_tile()`191 - Level 2: Copy partitioning (global → shared) with `TiledCopy`192 - Level 3: Compute partitioning (shared → register) with `TiledMMA`1934. **Shared memory**: Use swizzled layouts (`make_smem_layout_atom`) to avoid bank conflicts1945. **Mainloop**: K-tile loop with copy → sync → MMA → sync1956. **Pipeline**: Use `PipelineTmaAsync` (Hopper) or `PipelineTmaUmma` (Blackwell).196 ⚠️ TMA-based pipelines manage data movement via TMA descriptors — adding197 extra tensors (bias, activation inputs) to the epilogue requires modifying198 descriptor setup, which is prohibitively complex. See the stop condition in199 Workflow 0 step 4.2007. **Epilogue**: Predicated store with alpha/beta scaling2018. **Pre-compile with `cute.compile()`**: Always pre-compile the GEMM kernel202 so `kernel_fn` calls the compiled object, not `@cute.jit` directly.203 Without pre-compilation, every call recompiles (~20-50ms overhead).2049. **Autotune**: Search over tile sizes, cluster shapes, pipeline depths205206### Workflow 3: Framework Integration207208For wrapping CuTe DSL kernels as PyTorch/JAX custom operators.2092101. **Write kernel** using Workflow 1 or 22112. **Create wrapper**: Accept `torch.Tensor`, convert via `from_dlpack`, call host fn2123. **For production**: Compile with TVM FFI for zero-overhead tensor passing:213 ```python214 compiled = cute.compile(host_fn, *fake_tensors, options="--enable-tvm-ffi")215 compiled(torch_a, torch_b) # Direct torch.Tensor, no from_dlpack216 ```2174. **For deployment**: Use AOT compilation → export to `.o` → load at runtime218219### Workflow 4: Debugging & Profiling2202211. **Set environment**: `CUTE_DSL_PRINT_IR=1`, `CUTE_DSL_KEEP_PTX=1`2222. **Use `cute.printf()`** for runtime values (not Python `print`)2233. **Inspect generated code**: `compiled.__ptx__`, `compiled.__mlir__`2244. **Profile**: Enable `CUTE_DSL_LINEINFO=1`, use Nsight Compute/Systems2255. **Debug memory**: Run with `compute-sanitizer python script.py`226227## Output Formats228229A typical CuTe DSL kernel project:230231```232kernel_dir/233 kernel.py # @cute.kernel + @cute.jit functions234 test_kernel.py # Correctness test vs PyTorch reference235 bench_kernel.py # Benchmark with cute.compile() setup236```237238**Success indicators:**239- Correctness test passes (`torch.testing.assert_close`)240- Nsight shows vector loads (LDG.128/LDG.256), not scalar loads241- For GEMM: tensor core utilization > 80% in Nsight Compute242243## Companion Script Contract244245Kernel files used with `scripts/verify_kernel.py` and `scripts/benchmark_kernel.py`246must export three names:247248- `kernel_fn(*inputs)` — the CuTe DSL kernel wrapper (calls `cute.compile` + runs kernel)249- `reference_fn(*inputs)` — PyTorch reference implementation (same signature)250- `get_inputs()` — returns a list of CUDA tensors for testing251252```python253# Example kernel.py contract254import torch255import cutlass.cute as cute256from cutlass.cute.runtime import from_dlpack257258def kernel_fn(x):259 out = torch.empty_like(x)260 # ... call compiled cute kernel ...261 return out262263def reference_fn(x):264 return torch.nn.functional.gelu(x)265266def get_inputs():267 return [torch.randn(1024, 512, dtype=torch.float16, device="cuda")]268```269270## Examples271272### Example: 2D Unary Element-wise (ReLU)273274```python275import torch, cutlass, cutlass.cute as cute276from cutlass.cute.runtime import from_dlpack277278@cute.kernel279def relu_kernel(gA: cute.Tensor, gC: cute.Tensor):280 tidx, _, _ = cute.arch.thread_idx()281 bidx, _, _ = cute.arch.block_idx()282 bdim, _, _ = cute.arch.block_dim()283 idx = bidx * bdim + tidx284 m, n = gA.shape[1]285 total = m * n286 if cutlass.dynamic_expr(idx < total):287 a = gA[(None, (idx // n, idx % n))].load()288 gC[(None, (idx // n, idx % n))] = cute.where(a > 0, a, 0)289290@cute.jit291def relu_host(mA: cute.Tensor, mC: cute.Tensor):292 vec = 16 // (mA.element_type.width // 8)293 gA = cute.zipped_divide(mA, (1, vec))294 gC = cute.zipped_divide(mC, (1, vec))295 T = 256296 N = cute.size(gA.shape[1])297 relu_kernel(gA, gC).launch(grid=((N+T-1)//T,1,1), block=(T,1,1))298299x = torch.randn(1024, 512, dtype=torch.float16, device="cuda")300out = torch.empty_like(x)301relu_host(from_dlpack(x, assumed_align=16), from_dlpack(out, assumed_align=16))302```303304## Error Handling305306| Error | Cause | Fix |307|-------|-------|-----|308| `MLIR function requires a Context` | Called @kernel from Python | Launch via @cute.jit host function |309| `DSLAstPreprocessorError` on return | Early return in @kernel | Use `if cutlass.dynamic_expr(cond):` |310| Type mismatch on store | `a * 2` promotes FP16→FP32 | Use `a + a` or `.to(cutlass.Float16)` |311| `could not get source code` | Kernel in `exec()` context | Write to file and import |312| Scalar loads in Nsight | Missing alignment hint | Add `assumed_align=16` to `from_dlpack` |313| `Missing required argument` | Not all @jit params passed | Pass ALL declared parameters |314| `AttributeError: sigmoid` | No `cute.math.sigmoid` | Use `1.0/(1.0+cute.math.exp(-x))` |315316See `references/troubleshooting.md` for the full error table and limitations.317318**Debugging rule:** Never delete kernel.py during debugging. Use `backup_file`319to save a checkpoint, then `edit_file` to iterate. If stuck, `revert_file` to320restore the backup. A partially-working kernel is always better than no kernel.321322## Finding More Information323324### Tier 1: This File (SKILL.md)325326Workflows above cover element-wise kernels, GEMM, framework integration, and327debugging. Search this file first for procedural questions.328329### Tier 2: references/ Directory330331Grep for keywords across `references/`. Headers are grep-friendly.332333| File | Content |334|------|---------|335| `concepts-architecture.md` | Core abstractions, terminology, compilation pipeline |336| `concepts-layouts.md` | Layout algebra: composition, complement, divide, swizzle |337| `concepts-tensors.md` | Tensor types, partitioning, tiling, predication |338| `concepts-mma.md` | MMA atoms, TiledMMA, per-architecture tensor core ops |339| `patterns-getting-started.md` | Installation, decorators, first kernel walkthrough |340| `patterns-elementwise.md` | Invariant principles, pattern variations, reference impl |341| `patterns-gemm.md` | 3-level tiling, shared memory, pipelining, autotuning |342| `patterns-memory.md` | from_dlpack, TMA, cp.async, TMEM, copy atoms |343| `patterns-compilation.md` | Control flow, JIT caching, TVM FFI, AOT compilation |344| `patterns-pipeline.md` | Producer-consumer, pipeline classes, barriers, warp specialization |345| `api-core.md` | cute module: layouts, tensors, math, copy, gemm, printing |346| `api-arch.md` | cute.arch: thread indexing, sync, atomics, memory ops |347| `api-nvgpu.md` | cute.nvgpu: warp/warpgroup/cpasync/tcgen05 MMA and copy |348| `api-runtime-utils.md` | Runtime: from_dlpack, fake tensors, utils, schedulers |349| `troubleshooting.md` | Debugging, env vars, common errors, limitations, FAQ |350351**How to search:** Grep for your keyword across `references/`. Read only the352file and section that Grep points to.353354### Tier 3: Original Documentation355356If Tiers 1–2 don't answer, consult the source:357- **Web**: https://docs.nvidia.com/cutlass/latest/358- **GitHub**: https://github.com/NVIDIA/cutlass359- Fetch specific doc pages or search for "CUTLASS CuTe DSL <topic>"360- Consider distilling the answer back into references/