Skip to content
LLM Inference

22 chapters · 9,450 lines of code · no GPU required

Build an LLMinference enginefrom scratch.

Anyone can call an inference API. Explaining why vLLM is 40× faster than a small PyTorch loop is harder, and that is the gap this course closes. You start from a plain generation loop and improve it one bottleneck at a time.

Every chapter comes with a mechanism-level diagram, a simulator you drive yourself, six questions with worked explanations, and a file you can run that checks what the chapter claims.

$ pip install numpy && python code/s01_generation_loop.py

Chapter 1 · the whole engine

ONE ITERATION = ONE TOKENprompt"The cat"tokenizertext → idsforward passL × decoder blocklogits[vocab_size]samplerargmax / top-ptoken"sat"append to context — next pass sees one more tokenif EOSdetokenize + emitids → textCONTEXT AFTER 3 ITERATIONSThecatsatonthematgrey = prompt (computed once, in parallel — the prefill)orange = generated (one per forward pass — the decode)Every pass re-reads the whole context. That is the cost S05 removes.

01

Start with the loop; then remove its bottlenecks.

An engine calls the model, samples a token, appends it, and repeats. The remaining chapters deal with what that short loop hides: repeated work, idle hardware, and memory that runs out.

02

Almost every optimisation is a memory optimisation.

Decode reads the entire model to produce one token, so the bottleneck is bytes moved rather than arithmetic. The KV cache, paging, prefix reuse and quantization all follow from that, and between them they take up most of the course.

03

Production engines become easier to read.

Each chapter maps its central idea onto vLLM, SGLang, llama.cpp, picoLM, or quant.cpp, so there is always a concrete file to open next.

The curriculum

Five layers, twenty chapters, two capstones

Each layer builds on a constraint the layer before it introduced. On a first pass, read the chapters in order; out of sequence, the dependencies stop being visible.

The Model

S01S04

Turn weights into tokens: tokenizer, transformer forward pass, sampler. This is the loop that exists before any optimisation.

…which leaves the loop correct and unusably slow. So:

Memory & KV Cache

S05S08

Almost every inference optimisation is a memory optimisation. Cache the KV, page it, share it, compress it.

…which makes memory the scarce resource, not FLOPs. So:

Batching & Scheduling

S09S12

One request wastes a GPU. Continuous batching, the scheduler, preemption, and chunked prefill keep it saturated.

…which saturates one GPU with many requests. So:

Decoding Acceleration

S13S16

Break the one-token-per-forward-pass rule, and constrain what the model is allowed to say.

…which is as fast as one machine gets. So:

Distributed Serving

S17S20

Split the model across GPUs, split prefill from decode across machines, and put an API in front of it.

The Capstone

S21S22

Take a real 2,944-line C engine and rebuild it in Python, module for module. It is the only chapter whose reference implementation is somebody else's shipping code.

In every chapter

A mechanism-level diagram

Follow the data as it moves, and see where computation, memory traffic and latency enter the system.

An interactive simulator

Push the inputs until an edge case shows up. Exhaust the KV pool, move a sampling threshold, and watch what the system does about it.

A quiz with explanations

Six graded questions per chapter, each with an explanation that points back to the relevant idea.

A file you can run

Self-contained and NumPy-only, apart from the TypeScript capstone, which runs with Node. It asserts its own claims and finishes in under two seconds. Nothing to download, no PyTorch, no GPU.

Begin with the generation loop.

Chapter 1 is nine lines of Python and one uncomfortable measurement. The rest of the course follows from that measurement.

S01 · The Generation Loop →