Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compilation Flow

At a high level, a model goes from traced graph to running device code like this:

graph LR
    A["Model (teeny-core nn::Layer)"] -->|trace| B["Graph (teeny-core::graph)"]
    B -->|lower| C["FXGraph"]
    C -->|compile| D["teeny-compiler backends"]
    D -->|LLVM/MLIR backend, via teenyc| E["Device object code"]
    D -->|ndarray backend| F["CPU (ndarray)"]
    E --> G["Device drivers (teeny-cuda, ...)"]
  • Trace: your model, built from teeny-core::nn layers, is called with a symbolic input, recording a teeny-core::graph::Graph — see Tensors & the Computational Graph.
  • Lower: the graph is lowered to FXGraph, teeny-compiler’s intermediate representation.
  • Compile: teeny-compiler (API docs) compiles FXGraph to a target backend:
    • The LLVM/MLIR backend shells out to the custom teenyc compiler at runtime (-Zcodegen-backend=mlir) — see The LLVM/MLIR Backend.
    • The ndarray backend (feature-gated, default-on) runs on CPU without teenyc.
  • Device drivers: compiled device code is loaded and run through a driver crate — today, teeny-cuda for NVIDIA GPUs. teeny-cpu and teeny-vulkan are planned but not yet implemented (only drivers/teeny-cuda exists in the workspace today).

Kernels themselves (the actual per-op device code, e.g. attention, matmul, elementwise ops) are defined separately — see Kernels & Backends.

Ahead-of-time vs. just-in-time

The same compilation pipeline can run either eagerly (JIT, at model-run time) or ahead of time (AOT, producing cached artifacts you deploy without a compiler on the target device) — see teeny-cli and Ahead-of-Time Compilation.