/triton-lang
Triton language skill for Python GPU kernel authoring. Use when writing Triton kernels with @triton.jit, tl.load/store, masking, atomics, benchmarking with triton.testing, or integrating kernels into PyTorch. Activates on queries about Triton, tl.constexpr, block pointers,
$ npx -y skills add mohitmishra786/low-level-dev-skills --skill triton-lang --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/triton-lang
Context preview
The summary Claude sees to decide when to auto-load this skill.
Triton language skill for Python GPU kernel authoring. Use when writing Triton kernels with @triton.jit, tl.load/store, masking, atomics, benchmarking with triton.testing, or integrating kernels into PyTorch. Activates on queries about Triton, tl.constexpr, block pointers,
SKILL.md
triton-lang.SKILL.mdname: triton-lang
description: Triton language skill for Python GPU kernel authoring. Use when writing Triton kernels with @triton.jit, tl.load/store, masking, atomics, benchmarking with triton.testing, or integrating kernels into PyTorch. Activates on queries about Triton, tl.constexpr, block pointers, Triton benchmarking, or PyTorch custom ops.
Triton
Purpose
Guide agents through writing GPU kernels in OpenAI Triton: the `@triton.jit` decorator, block-oriented `tl.load`/`tl.store` with masking, atomic operations, shared memory via `tl.constexpr`, benchmarking with `triton.testing.Benchmark`, PyTorch integration, and debugging with barriers.
When to Use
- Writing custom PyTorch ops faster than pure PyTorch but without raw CUDA
- Prototyping fused kernels (e.g., softmax + scale + bias)
- Comparing block sizes and warp counts with Triton's autotuner
- Porting NumPy-style elementwise ops to GPU
- Learning GPU programming with higher-level Python syntax
- Benchmarking kernel variants systematically
Workflow
1. Minimal Triton kernel
import torch
import triton
import triton.language as tl
@triton.jit
def add_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offsets = pid * BLOCK + tl.arange(0, BLOCK)
mask = offsets < n
x = tl.load(x_ptr + offsets, mask=mask)
y = tl.load(y_ptr + offsets, mask=mask)
tl.store(out_ptr + offsets, x + y, mask=mask)
def add(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
n = x.numel()
out = torch.empty_like(x)
grid = lambda meta: (triton.cdiv(n, meta["BLOCK"]),)
add_kernel[grid](x, y, out, n, BLOCK=1024)
return outKey concepts:
- `tl.program_id(0)` — block index (like `blockIdx.x`)
- `tl.arange(0, BLOCK)` — vector of thread indices within block
- `mask` — predication for tail elements (no separate bounds kernel)
- `BLOCK: tl.constexpr` — compile-time constant, enables unrolling
2. Load/store and masking
@triton.jit
def masked_load_example(ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
# masked load returns 0 for masked-off lanes
vals = tl.load(ptr + offs, mask=mask, other=0.0)
return valsBlock pointers (Triton 2.x+) for structured 2D access:
@triton.jit
def matvec_kernel(a_ptr, x_ptr, y_ptr, M, N, BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr):
pid_m = tl.program_id(0)
offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
acc = tl.zeros((BLOCK_M,), dtype=tl.float32)
for start_n in range(0, N, BLOCK_N):
offs_n = start_n + tl.arange(0, BLOCK_N)
a = tl.load(a_ptr + offs_m[:, None] * N + offs_n[None, :])
x = tl.load(x_ptr + offs_n)
acc += tl.sum(a * x[None, :], axis=1)
tl.store(y_ptr + offs_m, acc, mask=offs_m < M)3. Atomic operations
@triton.jit
def atomic_histogram(data_ptr, hist_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
data = tl.load(data_ptr + offs, mask=mask)
bucket = (data % 256).to(tl.int32)
tl.atomic_add(hist_ptr + bucket, 1, mask=mask)Use atomics sparingly — they serialize memory updates. Prefer block-level reduction then single atomic per block.
4. Shared memory via constexpr
@triton.jit
def reduce_kernel(x_ptr, out_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask, other=0.0)
# Block reduction
x = tl.sum(x, axis=0)
tl.atomic_add(out_ptr, x)`BLOCK` as `tl.constexpr` lets the compiler allocate shared memory and unroll loops at compile time.
5. Autotuning
@triton.autotune(
configs=[
triton.Config({"BLOCK": 128}, num_warps=4),
triton.Config({"BLOCK": 256}, num_warps=4),
triton.Config({"BLOCK": 512}, num_warps=8),
],
key=["n"],
)
@triton.jit
def tuned_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK: tl.constexpr):
# ... kernel body ...
passAutotuner benchmarks configs on first run and caches the best for each `key` shape.
6. Benchmarking
from triton.testing import Benchmark
def benchmark_add():
n = 1024 * 1024
x = torch.randn(n, device="cuda")
y = torch.randn(n, device="cuda")
def triton_add():
return add(x, y)
def torch_add():
return x + y
bench = Benchmark(
x_names=["n"],
x_vals=[2**i for i in range(10, 24)],
line_arg="provider",
line_vals=["triton", "torch"],
line_names=["Triton", "PyTorch"],
plot_name="add-bench",
args={},
)
bench.run(lambda n, provider: {
"triton": lambda: add(x[:n], y[:n]),
"torch": lambda: x[:n] + y[:n],
}[provider](), quantiles=[0.5, 0.9])# Quick timing in REPL
import triton.testing as tt
ms = tt.do_bench(lambda: add(x, y))
print(f"{ms:.3f} ms")7. PyTorch integration
import torch
from torch.library import custom_op
@custom_op("mylib::triton_add", mutates_args=())
def triton_add_op(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
return add(x, y)
@triton_add_op.register_fake
def _(x, y):
return torch.empty_like(x)
# Use in model
class MyModule(torch.nn.Module):
def forward(self, x, y):
return triton_add_op(x, y)For `torch.compile` compatibility, register fake/meta kernels and avoid Python side effects in the JIT function.
8. Debugging
@triton.jit
def debug_kernel(x_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask)
# Synchronize threads within block for inspection
tl.debug_barrier()
tl.store(x_ptr + offs, x * 2.0, mask=mask)# Dump generated PTX/LLVM IR
TRITON_PRINT_AUTOTUNING=1 pyth
Read more
name: triton-lang description: Triton language skill for Python GPU kernel authoring. Use when writing Triton kernels with @triton.jit, tl.load/store, masking, atomics, benchmarking with triton.testing, or integrating kernels into PyTorch. Activates on queries about Triton, tl.constexpr, block pointers, Triton benchmarking, or PyTorch custom ops.
Triton
Purpose
Guide agents through writing GPU kernels in OpenAI Triton: the `@triton.jit` decorator, block-oriented `tl.load`/`tl.store` with masking, atomic operations, shared memory via `tl.constexpr`, benchmarking with `triton.testing.Benchmark`, PyTorch integration, and debugging with barriers.
When to Use
- Writing custom PyTorch ops faster than pure PyTorch but without raw CUDA
- Prototyping fused kernels (e.g., softmax + scale + bias)
- Comparing block sizes and warp counts with Triton's autotuner
- Porting NumPy-style elementwise ops to GPU
- Learning GPU programming with higher-level Python syntax
- Benchmarking kernel variants systematically
Workflow
1. Minimal Triton kernel
import torch
import triton
import triton.language as tl
@triton.jit
def add_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offsets = pid * BLOCK + tl.arange(0, BLOCK)
mask = offsets < n
x = tl.load(x_ptr + offsets, mask=mask)
y = tl.load(y_ptr + offsets, mask=mask)
tl.store(out_ptr + offsets, x + y, mask=mask)
def add(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
n = x.numel()
out = torch.empty_like(x)
grid = lambda meta: (triton.cdiv(n, meta["BLOCK"]),)
add_kernel[grid](x, y, out, n, BLOCK=1024)
return outKey concepts:
- `tl.program_id(0)` — block index (like `blockIdx.x`)
- `tl.arange(0, BLOCK)` — vector of thread indices within block
- `mask` — predication for tail elements (no separate bounds kernel)
- `BLOCK: tl.constexpr` — compile-time constant, enables unrolling
2. Load/store and masking
@triton.jit
def masked_load_example(ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
# masked load returns 0 for masked-off lanes
vals = tl.load(ptr + offs, mask=mask, other=0.0)
return valsBlock pointers (Triton 2.x+) for structured 2D access:
@triton.jit
def matvec_kernel(a_ptr, x_ptr, y_ptr, M, N, BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr):
pid_m = tl.program_id(0)
offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
acc = tl.zeros((BLOCK_M,), dtype=tl.float32)
for start_n in range(0, N, BLOCK_N):
offs_n = start_n + tl.arange(0, BLOCK_N)
a = tl.load(a_ptr + offs_m[:, None] * N + offs_n[None, :])
x = tl.load(x_ptr + offs_n)
acc += tl.sum(a * x[None, :], axis=1)
tl.store(y_ptr + offs_m, acc, mask=offs_m < M)3. Atomic operations
@triton.jit
def atomic_histogram(data_ptr, hist_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
data = tl.load(data_ptr + offs, mask=mask)
bucket = (data % 256).to(tl.int32)
tl.atomic_add(hist_ptr + bucket, 1, mask=mask)Use atomics sparingly — they serialize memory updates. Prefer block-level reduction then single atomic per block.
4. Shared memory via constexpr
@triton.jit
def reduce_kernel(x_ptr, out_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask, other=0.0)
# Block reduction
x = tl.sum(x, axis=0)
tl.atomic_add(out_ptr, x)`BLOCK` as `tl.constexpr` lets the compiler allocate shared memory and unroll loops at compile time.
5. Autotuning
@triton.autotune(
configs=[
triton.Config({"BLOCK": 128}, num_warps=4),
triton.Config({"BLOCK": 256}, num_warps=4),
triton.Config({"BLOCK": 512}, num_warps=8),
],
key=["n"],
)
@triton.jit
def tuned_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK: tl.constexpr):
# ... kernel body ...
passAutotuner benchmarks configs on first run and caches the best for each `key` shape.
6. Benchmarking
from triton.testing import Benchmark
def benchmark_add():
n = 1024 * 1024
x = torch.randn(n, device="cuda")
y = torch.randn(n, device="cuda")
def triton_add():
return add(x, y)
def torch_add():
return x + y
bench = Benchmark(
x_names=["n"],
x_vals=[2**i for i in range(10, 24)],
line_arg="provider",
line_vals=["triton", "torch"],
line_names=["Triton", "PyTorch"],
plot_name="add-bench",
args={},
)
bench.run(lambda n, provider: {
"triton": lambda: add(x[:n], y[:n]),
"torch": lambda: x[:n] + y[:n],
}[provider](), quantiles=[0.5, 0.9])# Quick timing in REPL
import triton.testing as tt
ms = tt.do_bench(lambda: add(x, y))
print(f"{ms:.3f} ms")7. PyTorch integration
import torch
from torch.library import custom_op
@custom_op("mylib::triton_add", mutates_args=())
def triton_add_op(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
return add(x, y)
@triton_add_op.register_fake
def _(x, y):
return torch.empty_like(x)
# Use in model
class MyModule(torch.nn.Module):
def forward(self, x, y):
return triton_add_op(x, y)For `torch.compile` compatibility, register fake/meta kernels and avoid Python side effects in the JIT function.
8. Debugging
@triton.jit
def debug_kernel(x_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offs = pid * BLOCK + tl.arange(0, BLOCK)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask)
# Synchronize threads within block for inspection
tl.debug_barrier()
tl.store(x_ptr + offs, x * 2.0, mask=mask)# Dump generated PTX/LLVM IR TRITON_PRINT_AUTOTUNING=1 pyth
A curated suite of AI agent skills for systems and low-level programming — C/C++, Rust, Zig, GPU, bare-metal firmware, Linux kernel/driver development, computer architecture, compiler internals, HPC, and more.
Repo: mohitmishra786/low-level-dev-skills
Other skills on low-level-dev-skills.
- /custom-allocators
Custom allocator skill for memory allocation strategies. Use when implementing pool/slab/arena allocators, tuning jemalloc/mimalloc, writing Rust GlobalAlloc, or benchmarking allocator performance. Activates on queries about jemalloc, mimalloc, tcmalloc, arena allocator,
Open skill - /numa-programming
NUMA programming skill for multi-socket memory locality. Use when detecting NUMA topology, binding processes with numactl, using libnuma API, building NUMA-aware data structures, or measuring remote access penalties. Activates on queries about numactl, libnuma, NUMA topology,
Open skill - /af-xdp
AF_XDP skill for high-performance XDP sockets. Use when creating AF_XDP sockets, configuring UMEM and XSK rings, XDP_REDIRECT programs, copy vs zero-copy mode, or comparing with DPDK. Activates on queries about AF_XDP, xsk_umem, XDP_REDIRECT, libbpf xsk, or zero-copy XDP.
Open skill - /dpdk
DPDK skill for userspace packet I/O. Use when initializing EAL, configuring PMD drivers, using mbuf pools and rte_ring, setting up huge pages, RSS, or testpmd validation. Activates on queries about DPDK, EAL, rte_eth_rx_burst, hugepages, PMD, or testpmd.
Open skill - /io-uring
io_uring skill for Linux async I/O. Use when building high-performance servers with liburing, multi-shot operations, provided buffers, fixed files, zero-copy send, or tokio-uring. Activates on queries about io_uring, SQE/CQE, liburing, IORING_OP_PROVIDE_BUFFERS, or io_uring vs
Open skill - /adc-dac-baremetal
Bare-metal ADC and DAC skill. Use when configuring analog sampling, DMA-driven ADC, calibration, or DAC output on MCUs. Activates on queries about ADC bare-metal, sampling time, DMA ADC, or DAC channel setup.
Open skill

