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::nnlayers, is called with a symbolic input, recording ateeny-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
teenyccompiler at runtime (-Zcodegen-backend=mlir) — see The LLVM/MLIR Backend. - The
ndarraybackend (feature-gated, default-on) runs on CPU withoutteenyc.
- The LLVM/MLIR backend shells out to the custom
- Device drivers: compiled device code is loaded and run through a driver crate — today,
teeny-cudafor NVIDIA GPUs.teeny-cpuandteeny-vulkanare planned but not yet implemented (onlydrivers/teeny-cudaexists 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.