The memory wall — your GPU is a chef waiting on deliveries
A modern GPU can do ~1,000 trillion multiply-adds per second, but can only fetch ~3 TB/s from its main memory (HBM). So the question for any operation isn't "how much math?" — it's how much math per byte fetched (arithmetic intensity). Drag the slider and watch the utilization gauge: heavy-math ops keep the chef cooking; naive attention keeps him standing at the loading dock.
The gauge implements the roofline model: achievable FLOPs = min(peak compute, intensity × bandwidth), with H100-class numbers (989 TFLOPs, 3.35 TB/s). The break-even intensity ≈ 295 ops/byte falls out of the division.
The N² tourist — a giant matrix that only exists in transit
Naive attention computes the N×N score matrix, writes all of it to slow memory, then immediately reads it back to apply softmax and multiply by V. It's a tourist: it visits HBM once and contributes nothing. Drag the sequence length and read the bill — at 32k tokens, that round-trip is gigabytes per attention head, and it grows with the square.
Traffic = 2 × N² × 2 bytes (write + read of fp16 scores) per head; the animation shows the round trip. FLOPs for the same work = 2·N²·d — the ratio between the bars is the whole problem.
Tiling — cook from the pantry, not the warehouse
Next to its huge slow memory, a GPU has a tiny fast one: SRAM — ~200 KB per compute block, but ~50× faster. The trick: chop Q, K, V into tiles that fit in the pantry, compute a block of attention entirely on-chip, fold it into the running output, and move on. The N² matrix still gets computed — it just never exists in one place. Pick a tile size: too big won't fit, too small drowns in loading overhead.
Traffic counters accumulate live during the animation: naive counts every score byte twice; tiled counts only Q/K/V/O block loads. The ~N²·d/M ratio (M = SRAM size) is measured off your run, not asserted.
The softmax puzzle — how to average what you haven't seen
Here's why nobody tiled attention for five years: softmax needs the whole row — its max (for numerical stability) and its total sum — before any single weight is final. But tiles arrive one at a time. The fix is the online softmax: keep a running max and running sum, and every time a new tile brings a bigger max, rescale everything you've accumulated so far. Step through a row below and watch the books stay balanced — then run the naive streamer that skips the rescale and watch it silently produce garbage.
Real numbers: the row's scores are random each reset; both the tile-by-tile ledger (running max m, running sum ℓ, rescale factor) and the ground-truth full softmax are computed live and compared at the end.
Race them yourself — a real benchmark in your tab
No simulation this time. The button below runs two real implementations of attention in JavaScript, right here: a naive one that genuinely allocates the full N×N score matrix, and a streaming-tiled one with the online softmax from EP 04 that never holds more than one tile. Wall-clock times from your own CPU, memory allocated counted exactly, outputs cross-checked for equality.
Honesty label: your browser has no HBM/SRAM split, so speedups here come from cache behavior and allocation cost — smaller than on a GPU (where FlashAttention gains 2-10×), but the memory asymptotics (O(N²) vs O(N)) are identical and measured exactly. Outputs are verified equal to 1e-10 every run.