From compiler foundations to frontier systems
Building an ML Compiler from Scratch
The book follows one small compiler, uopc, as it is built week by week: a graph IR and a rewrite
engine first, then C code generation, loops, kernel fusion, automatic differentiation, CPU and GPU optimization,
and training a GPT. Continue through compiler analysis, GPU engineering, dynamic execution, numerical methods,
and distributed systems, with runnable labs and a frontier-lab preparation track.
- Chapters
- 37
- Diagrams
- 46
- Words
- 269k
- Compiler
- 2,803 lines
gemm.uirinput
# C = A @ B for 4x4 matrices, from movement ops only %0 = buffer 16 : dtype=f32 slot=0 %1 = buffer 16 : dtype=f32 slot=1 %2 = reshape %0, (4, 1, 4) %3 = reshape %1, (4, 4) %4 = permute %3, (1, 0) %5 = reshape %4, (1, 4, 4) %6 = mul %2, %5 %7 = reduce %6 : op=add pop=1
parse → rangeify → simplify → linearize → render
gemm.cgenerated by uopc
void gemm(float* restrict data0, float* restrict data1, float* restrict data2) { for (int ridx0 = 0; ridx0 < 4; ridx0++) { int alu1 = (ridx0*4); for (int ridx1 = 0; ridx1 < 4; ridx1++) { float acc0; acc0 = 0.0f; for (int ridx2 = 0; ridx2 < 4; ridx2++) { float val2 = acc0; float val3 = data0[(alu1+ridx2)]; float val4 = data1[((ridx2*4)+ridx1)]; acc0 = (val2+(val3*val4)); } float val5 = acc0; data2[(alu1+ridx1)] = val5; } } }
MNIST, week 5
94%
test accuracy, 15 ms per step
GEMM 1024³, week 6
321
GFLOP/s, from 5 naive (numpy: 449)
Flash attention, week 6
3 ways
unfused, fused, online softmax
GPT, weeks 9–10
2.11
val loss on Tiny Shakespeare, from 3.83
Contents
Front matter
Front matter
Part I
The IR
Part II
From graphs to machine code
Part III
A real compiler
Part IV
Making it fast
Part V
Accelerators
Part VI
Real models
Appendices
Part VII
Advanced engineering
- Advanced trackThe Syllabus Contract and Completion Gates
- Advanced trackControl Flow, SSA, Analysis, and Lowering
- Advanced trackGPU Engineering: Correctness, Throughput, and Attention
- Advanced trackSymbolic Shapes, Guards, Mutation, and Graph Capture
- Advanced trackMemory Planning, Precision, and Distributed Execution
- CapstoneFrom Course Completion to Independent Engineering
Part VIII
Frontier systems and research
Part IX
Implementing deeper compilers
- Compiler internalsBuilding a Source Compiler: Contracts, CFGs, and SSA Construction
- Compiler internalsOptimization with Executable-Path Reasoning
- Compiler internalsExecuting SSA, Destroying Phis, and Allocating Registers
- Tensor compilerA Dynamic Tensor Compiler with Fusion and Planned Memory
- Training compilerDifferentiating and Training Through the Dynamic Compiler
- GPU implementationRegister-Tiled GEMM on a Real GPU
Run it yourself
Python 3.11+, numpy and gcc with OpenMP. An NVIDIA GPU is optional; GPU kernels are also checked on the CPU through an emulator.
git clone https://github.com/StarAtNyte/ml-compiler-from-scratch.git
cd ml-compiler-from-scratch
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest -q # 102 tests
.venv/bin/python examples/mnist_mlp.py # train MNIST with your compiler
.venv/bin/python examples/gpt.py # train a GPT, then sample from it