Nvidia tensorrt llm kernel cute writing
Skill autohandai/community-skills/nvidia-tensorrt-llm-kernel-cute-writing
'Write and implement GPU kernels using NVIDIA CuTe DSL (CUTLASS 4.x Python API) — NOT for Triton, CUDA C++, or conceptual explanations. Trigger only when the user wants to write or implement a kernel, not when asking questions about CuTe DSL concepts or layouts. CuTe DSL uses cute.jit/cute.kernel decorators and cutlass.cute imports. Covers element-wise kernels, GEMM patterns, reductions, memory hierarchy (global/shared/register/TMA), MMA tensor core operations, software pipelining, and framework integration.From its SKILL.md
npx -y skills add autohandai/community-skills --skill nvidia-tensorrt-llm-kernel-cute-writingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
16.7 KB, ~4.4k tokens by cl100k_base, as published. Nobody here has run it
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_fetchwith base URLhttps://raw.githubusercontent.com/NVIDIA/cutlass/main/examples/python/CuTeDSLOperation Arch Example path (append to base URL) Element-wise add SM80 ampere/elementwise_add.pyElement-wise + autotune SM80 ampere/elementwise_add_autotune.pyElement-wise apply SM80 ampere/elementwise_apply.pySGEMM (scalar) SM80 ampere/sgemm.pyTensor-core GEMM SM80 ampere/tensorop_gemm.pyFlash Attention v2 SM80 ampere/flash_attention_v2.pyHSTU Attention SM80 ampere/hstu_attention.pyShared memory allocator SM80 ampere/smem_allocator.pyCTA norm (LayerNorm) SM90 hopper/cta_norm.pyDense GEMM SM90 hopper/dense_gemm.pyDense GEMM persistent SM90 hopper/dense_gemm_persistent.pyFlash MHA SM90 hopper/fmha.pyDense GEMM SM100 blackwell/dense_gemm.pyDense GEMM persistent SM100 blackwell/dense_gemm_persistent.pyDense GEMM + alpha/beta SM100 blackwell/dense_gemm_alpha_beta_persistent.pyRMSNorm SM100 blackwell/rmsnorm.pyReduce SM100 blackwell/reduce.pyFlash MHA SM100 blackwell/fmha.pyGrouped GEMM SM100 blackwell/grouped_gemm.pyMamba2 SSD SM100 blackwell/mamba2_ssd/GEMM tutorial (notebook) SM100 notebooks/tour_to_sol_gemm.ipynbExample: 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.compilewithmark_layout_dynamic, shared memory layouts) - For reductions:
references/patterns-reduction.md(warp reductions,cute.compilecache 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.
- For GEMM:
-
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 callfrom_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.pyThe kernel file must export
kernel_fn,reference_fn, andget_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_sizefromelement_type.width - P3:
cute.zipped_divide(mA, tiler)for coalesced access - P4:
cutlass.dynamic_expr(thread_idx < total)for bounds
- P1:
- Critical rules: No early return, no
a * 2(usea + a), nocute.math.sigmoid - Pre-compile with
cute.compile(): Always pre-compile the kernel once usingcute.compile()so thatkernel_fncalls the compiled object, not@cute.jitdirectly. 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:
The kernel file must exportpython scripts/verify_kernel.py kernel.py --rtol 1e-3 --atol 1e-3kernel_fn,reference_fn, andget_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
- Level 1: CTA tiling with
- 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) orPipelineTmaUmma(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 sokernel_fncalls the compiled object, not@cute.jitdirectly. 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 viafrom_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 Pythonprint) - 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 (callscute.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:
- Web: https://docs.nvidia.com/cutlass/latest/
- GitHub: https://github.com/NVIDIA/cutlass
- Fetch specific doc pages or search for "CUTLASS CuTe DSL <topic>"
- Consider distilling the answer back into references/
What ships with it: 20 files
137.4 KB alongside SKILL.md, 3 of them executable
references/
- api-arch.md5.0 KB
- api-core.md7.1 KB
- api-nvgpu.md6.6 KB
- api-runtime-utils.md5.9 KB
- concepts-architecture.md4.5 KB
- concepts-layouts.md5.9 KB
- concepts-mma.md5.2 KB
- concepts-tensors.md5.6 KB
- patterns-compilation.md6.7 KB
- patterns-elementwise.md7.5 KB
- patterns-gemm.md9.2 KB
- patterns-getting-started.md5.7 KB
- patterns-memory.md5.9 KB
- patterns-pipeline.md6.8 KB
- patterns-reduction.md7.2 KB
- troubleshooting.md6.2 KB
scripts/
- benchmark_kernel.pyruns11.5 KB
- __init__.pyruns684 B
- verify_kernel.pyruns12.3 KB
- LICENSE11.9 KB