teenygrad / Kernels & Backends
The #[kernel] Macro
Fully documented in the kernels book: What #[kernel]
Generates.
teeny-macros provides
the #[kernel] attribute macro (teeny_macros::kernel), which marks a function
as a kernel definition consumed by teeny-triton/teeny-kernels.
What it emits
From one annotated function, three items:
- Your function, unchanged. It type-checks as ordinary Rust. Nothing calls it — the macro converts its tokens back to a string, and that string is what the GPU compiler sees.
- A struct, named by PascalCasing the function name:
vector_addbecomesVectorAdd. Const generics become runtime fields, lowercased —const BLOCK_SIZEbecomesblock_size, and an argument tonew(). It implementsteeny_core::device::program::Kernel. - A dispatcher, only when you pass
dtypes = [...]orbackward = .... It maps a runtimeDtypeReprto a monomorphized kernel.
It also generates an extern "C" entry point, as text, with the generics filled
in — {name}_entry_point — because teenyc cannot call a generic Rust
function. That symbol is what the loader resolves.
Arguments
#[kernel] // no dispatch
#[kernel(backward = GeluBackward)] // pair with a gradient kernel
#[kernel(dtypes = [f32, f64])] // explicit dtype set
backward opts into dispatch too, inferring the dtype set from the dtype
parameter’s trait bound.
See Compile-Time Parameters and Dtype Dispatch for the inference rules, and Common Compile Errors for the macro’s diagnostics and what they mean.
Where to go
| You want | Read |
|---|---|
| The generated struct, field by field | What #[kernel] Generates |
| The real generated entry point | Same chapter — it quotes the committed snapshot |
| How a kernel fits the pipeline | Writing a Triton Kernel |
What teenyc does with the text |
From Rust to PTX |