Daily build log
One short doc per day: what was added, why, and what was learned. Newest entries sort to the bottom; the full plan they follow is in The 100-day plan.
Table of contents
- Day 01: scaffolding and the plan
- Day 02: weights, config, and a verification harness
- Day 03: the loader, and the name-mapping rabbit hole
- Day 04: RMSNorm and RoPE, position as a rotation
- Day 05: SwiGLU, the gated MLP every modern model uses
- Day 06: GQA attention, the one sublayer that mixes tokens
- Day 07: one full transformer block, end to end vs HuggingFace
- Day 08: the full forward pass, matching HuggingFace to 2.4e-5
- Day 09: greedy decode, the whole continuation matches HuggingFace
- Day 10: sampling, pinned bit-for-bit to the HuggingFace warpers
- Day 11: the KV cache, 5.7x faster and token-for-token identical
- Day 12: sampling meets the cache, one decode loop for greedy and sampling
- Day 13: the cache as a curve, not a number, and a benchmark that checks itself
- Day 14: the block allocator, paging for attention starts as pure bookkeeping
- Day 15: the block table, address translation for a scattered sequence
- Day 16: the paged KV cache, real K/V through scattered blocks
- Day 17: paging under the sampling path, free-and-reuse closes Week 5
- Day 18: the torch reference for paged attention, Week 6 opens
- Day 19: the fused paged read wired into attention
- Day 20: the number the Triton kernel has to beat
- Day 21: the Triton programming model, modeled on the CPU
- Day 22: the fused paged-attention kernel, modeled on the CPU
- Day 23: the real triton.jit paged-attention kernel
- Day 24: the scaling fit, reading the exponent off the sweep
- Day 25: the fused read dispatches to the kernel backend
- Day 27: many ragged prompts, one padded forward
- Day 28: one pool, one block table per sequence
- Day 29: static batching, measured
- Day 30: a request is a state, not a row index
- Day 32: the acceptance test, both loops on one clock
- Day 33: blocks a step at a time, and the eviction that pays for it
- Day 34: the recompute bill, put on the invoice
- Day 35: the invariants, checked between every iteration
- Day 36: the edge cases, and the watermark finally measured
- Day 37: an async server over a synchronous GPU loop
- Day 38: how many blocks fit
- Day 39: the stream, and the token that is half a character
- Day 40: one logits tensor, four callers who disagree
- Day 41: the acceptance test, and the caller nobody heard leave
- Day 42: the benchmark, and the queue a closed loop cannot see
- Day 43: the time to first token, taken apart from the inside
- Day 44: the outside baseline, and what a speedup is made of
- Day 45: the latency-throughput curve, and the knee as arithmetic
- Day 46: one decode step, taken apart, and the two clocks in it
- Day 47: the token that stopped coming home one row at a time
- Day 48: one journey home for k steps, and the rows it throws away
- Day 49: the compiler, the twelve places my own code cut the graph, and the integer that undid the rest
- Day 50: the addressing moved out of the forward, and the guard became a shape
- Day 51: the read rectangle stopped being built, and the length that could not be shared
- Day 52: the shape stopped moving, and the closed set that is too big to capture
- Day 53: the inputs stopped being built, and the witness that shared their storage
- Day 54: the step got recorded, and the output turned out to be a buffer too
- Day 55: the capture list moved to startup, and the dummy batch was all padding
- Day 56: the flags reached the launcher, and the graph limit was a width
- Day 57: the acceptance test, and the row the replay was reading
- Day 58: the persistent batch, and the move that is only a relabel
- Day 59: the rectangle the read builds, and the tile that replaces it
- Day 60: the read becomes a choice, and a counter is what can see it
- Day 61: the capture list loses its width axis, and the price changes currency
- Daily template