Skip to main content
Enigma provides two decorators for GPU code: @enigma.kernel for direct compute kernels and @enigma.jit for host-side functions that perform layout algebra and launch kernels.

@enigma.kernel

@enigma.kernel defines a GPU compute kernel. The decorated function is traced at compile time: the Python body runs once with symbolic IRValue placeholders, producing an IR graph that is then lowered to Metal.

Rules for kernel bodies

  • No native Python control flow — use enigma.for_range, enigma.if_, enigma.while_ instead.
  • No Python data types as values — all computation goes through IRValue objects.
  • No early returns — the tracer records the full body unconditionally.
  • Types are annotations, not runtime checksA: enigma.f32 declares the buffer’s element type.

Kernel parameters

Each parameter is one of:
  • enigma.f32, enigma.f16, enigma.bf16, enigma.i32, enigma.u32, etc. — typed buffer (pointer in Metal)
  • enigma.Scalar(dtype) — scalar constant, lowered as a 1-element buffer

Compiling a kernel

compiled is a CompiledKernel. Dispatch it with MetalRuntime.execute(...):

Repeated dispatch

For hot loops, pre-allocate buffers once:
For benchmarking:

@enigma.jit

@enigma.jit is a host-side function that runs at compile time. Use it when you need to:
  • Perform layout algebra (tiling, thread-value mapping) before generating kernels
  • Launch multiple kernels in sequence
  • Accept Tensor objects and compute block/thread partitioning

JIT function pattern

Compiling a JIT function


Control flow

Enigma provides tracing-compatible control flow wrappers:

enigma.for_range

Supports IRValue bounds, custom induction dtype, and carried state via init=[...]:

enigma.if_

enigma.while_

Predicated load/store

For boundary conditions without full control flow: