Exercise 3 — Online softmax: derive it, prove it, then count the bytes¶
No code. Work this on paper, then check
../solutions/03_online_softmax_math_solution.md.
This is the drill that separates "I can write a softmax kernel" from "I understand why FlashAttention exists." Interviewers ask part 2 and part 5 almost verbatim.
Notation¶
A single row of scores x[0..C-1]. Define, for the first k elements (1 ≤ k ≤ C):
m_k = max(x_0, ..., x_{k-1}) the running max
s_k = Σ_{i<k} exp(x_i - m_k) the running normalizer, shifted by m_k
The final answer is y_i = exp(x_i - m_C) / s_C.
Part 1 — The max trick is free¶
- Show in one line that
exp(x_i - m) / Σ_j exp(x_j - m) = exp(x_i) / Σ_j exp(x_j)for any constantm— not just the max. - Given that any
mworks, why ism = max(x)the right choice? State the property of every exponentx_i - mthat this choice guarantees. - What is the largest possible value of
Σ_j exp(x_j - m)whenm = max(x), and the smallest? Use this to argue the normalizer can never overflow. - Underflow:
expreturns exactly0in fp32 once the argument drops below about-87.3. If a row contains one score at+50and the rest at-50, what does the safe formula produce for the small scores, and is that answer wrong?
Part 2 — Derive the online update¶
You are streaming the row one element at a time and hold only the pair (m_k, s_k).
Element x_k arrives.
- Write
m_{k+1}in terms ofm_kandx_k. - Starting from the definition of
s_{k+1}, derive the update
Show every step. The whole derivation is one multiply-and-divide of exp(m_k) —
name the factor you insert and where it cancels.
3. Prove that the rescale factor exp(m_k - m_{k+1}) is always in (0, 1]. Why does
that make the update overflow-proof?
4. When does the rescale factor equal exactly 1, and what does the update reduce to
then? (This is the common case — quantify how often it fires for a random row.)
Part 3 — Prove equivalence with the 3-pass algorithm¶
- By induction on
k, prove that the streaming recurrence produces exactly(m_C, s_C)as defined above — i.e. the online algorithm is not an approximation. - Now the parallel version. Two threads each processed part of the row and hold
(m_a, s_a)and(m_b, s_b). Write the merge operator. - Prove the merge is associative and commutative, and identify its identity element. Why does the curriculum care — what does a monoid buy you on a GPU?
- Where exactly does the merge produce
NaN, and what single comparison prevents it?
Part 4 — Numerical thresholds¶
Fill in this table. ln(MAX) is the largest x for which exp(x) is finite.
| Format | Largest finite value | exp(x) overflows above x ≈ |
mantissa bits |
|---|---|---|---|
fp32 (float) |
|||
fp16 (half) |
|||
| bf16 |
- Attention logits before scaling routinely reach tens or hundreds. Which of the three formats is unusable for a naive softmax, and which is also risky for the safe one?
- Why does
1/sqrt(d_head)scaling reduce — but not remove — the need for the max trick? - A colleague proposes computing the exponentials in fp16 to halve the bandwidth, and
accumulating the normalizer in fp32. Is that safe? What breaks first as
Cgrows?
Part 5 — Count the HBM bytes¶
Setup: R = 8192 rows, C = 4096 columns, fp32, one block per row. Assume nothing
is cached across passes (the honest worst case for long rows).
- How many bytes is one row? The whole tensor?
- For each variant, count the row traversals (reads + the write) and turn that into total bytes for the tensor:
| Variant | reads | writes | traversals | total bytes |
|---|---|---|---|---|
| safe 3-pass | ||||
| online, statistics in one pass | ||||
| online + row cached on-chip |
- At an achieved bandwidth of 2.0 TB/s, what is the lower-bound runtime of each variant? Express the online-2-pass and cached-1-pass numbers as a speedup over the 3-pass version.
- Arithmetic intensity: softmax does roughly one
exp, one compare, one add and one multiply per element. Takingexpas ~8 FLOP, compute FLOP/byte for the cached variant. Compare against a ridge point of ~35 FLOP/byte. Memory- or compute-bound? - The catch. At
C = 128(a small vocabulary or head dim) the row is 512 B and every pass hits L2 or even L1. Does the pass count still decide the runtime? What does? State the row size at which you would expect the pass-count model to start predicting reality on a GPU with a 256 MB last-level cache and 8192 resident rows.
Part 6 — The bridge to FlashAttention¶
- In attention, softmax is followed immediately by
P · V. Explain why that lets you avoid ever writing theS × Sprobability matrix to HBM. - FlashAttention processes K/V in tiles and keeps a running output accumulator
Oalongside(m, s). When a new tile raises the max, bothsandOmust be rescaled. Write the update forO. - What does this buy asymptotically: state the HBM traffic of standard attention and of
FlashAttention in terms of sequence length
N, head dimd, and on-chip tile size.
Bonus¶
Derive log_softmax(x)_i = (x_i - m) - log(s) from the safe softmax, and explain in one
sentence why cross-entropy is computed from that expression rather than from
log(softmax(x)_i).