teenygrad / Kernels & Backends
Writing a Triton Kernel
Kernel authoring has its own book: Writing GPU Kernels in Rust.
It starts at what a GPU kernel is, assumes no CUDA experience, and goes as far as attaching a custom kernel to a model’s graph with a backward pass. This page is the two-minute version and a map into it.
The shape of a kernel
A kernel is a function generic over the
teeny-triton DSL’s
Triton trait plus a dtype, marked with #[kernel]:
#[kernel]
pub fn vector_add<T: Triton, D: Num, const BLOCK_SIZE: i32>(
a_ptr: T::Pointer<D>,
b_ptr: T::Pointer<D>,
out_ptr: T::Pointer<D>,
n_elements: i32,
) where
T::I32Tensor: types::Tensor<i32, 1>,
T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
{
let pid = T::program_id(Axis::X);
let offsets = T::arange(0, BLOCK_SIZE) + pid * BLOCK_SIZE;
let in_bounds = offsets.lt(n_elements);
// ... load, compute, store
}
You write what one program does with one block of the data — not what
one thread does with one element. program_id is how a program finds its slice.
How it compiles
At teeny-triton’s own build time, build.rs reads the DSL source under
src/triton/ (plus teeny-core’s dtype definitions) and embeds it as a string
constant (teeny_triton::triton_lang::TRITON) — pure text processing, no
compiler invocation.
At your kernel’s compile time (via teeny-compiler’s LLVM/MLIR backend), that
DSL text plus your kernel’s source is written out and compiled by the custom
teenyc compiler — see
The LLVM/MLIR Backend.
The consequence worth knowing up front: your kernel function is never called by your program. Its source text is the artefact.
Where to go
| You want | Read |
|---|---|
| To run a kernel today | Vector Add, End to End |
| The programming model | You Program a Block, Not a Thread |
| Why the source is captured as text | From Rust to PTX |
| Loads, stores and masking | Loads, Stores, and Masks |
| Every DSL operation | Python Triton to Rust |
| A kernel inside a model | Your Kernel as a Graph Op |
For a large, well-documented in-tree example, see
kernels/teeny-kernels/src/nn/attention/flash_attn2.rs (Flash Attention 2,
forward and backward).