Phase 00 — The FLOPs & Memory Algebra of Pre-Training
The phase where "we should train a bigger model" stops being an opinion and becomes an equation. Feinberg opens his Princeton talk with a question — "If I give you a certain amount of compute C (e.g. 1000 H100 for 30 days), what is the best LLM you can train? What should be its size (=N)? How many tokens (=D) should it be trained on?" — and immediately hands you the tool:
C = 6NDis a very good approximation of FLOPs. This phase makes that equation, its derivation, and its four failure modes yours permanently.
Why this phase exists
Every downstream phase is an application of this algebra:
- Phase 01 fits a scaling law over
C, which you compute with6ND. - Phase 02 optimizes lifetime cost =
6ND(train) +2N·D_inf(serve). - Phase 03 asks what
Neven means for an MoE (answer: active, not total). - Phase 05's roofline is this arithmetic divided by hardware constants.
- Phase 08's power model is this arithmetic multiplied by joules per bit.
If 6ND is a formula you memorized rather than derived, all of that becomes cargo cult. So
this phase does the derivation properly, then builds the calculator.
There is a second reason, and it is the practical one: this is what a frontier interview
actually opens with. "You have 1,000 H100s for 30 days. What do you train?" A candidate who
reaches for a framework has already failed. A candidate who converts chips × days into FLOPs,
FLOPs into (N, D), and then sanity-checks against HBM capacity has demonstrated the entire
job in four minutes.
Concept map
┌──────────────────────┐
│ BUDGET │
│ chips × days × MFU │
└──────────┬───────────┘
│ × peak FLOP/s
▼
┌──────────────────────┐
│ C (total FLOPs) │
└──────────┬───────────┘
│ C = 6ND
┌─────────────┴─────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ N (parameters) │ │ D (tokens) │
└────────┬─────────┘ └──────────────────┘
│
┌──────────┼──────────────┬────────────────────┐
▼ ▼ ▼ ▼
weights optimizer activations KV cache
2N bytes states (checkpointing) at serve time
(bf16) 6-12N bytes 2·L·H_kv·d_h·S·B·2
│
▼
┌────────────────────────────────┐
│ DOES IT FIT? (HBM capacity) │
│ if no → shard (Phase 04) │
└────────────────────────────────┘
What you will be able to do
- Derive
2Nforward /4Nbackward /6Ntotal from the definition of a matmul, in under two minutes, on a whiteboard. - Compute the exact per-step FLOP count of a transformer from its shapes — reproducing
Feinberg's slide identity
18BTDF + 24BTDNH = 6·BT·(3DF + 4DNH)— and say which term is the MLP and which is attention. - State the four regimes where
6NDbreaks (attention at long context, MoE, embeddings, activation checkpointing) and estimate the error in each. - Compute training memory: weights + gradients + optimizer states + activations, and say which term dominates at which scale.
- Compute KV-cache size and show how GQA changes it by the group factor.
- Convert between: chips × days ↔ FLOPs ↔
(N, D)↔ dollars ↔ joules. - Answer "1,000 H100 for 30 days — what do you train?" with a number and a defence.
The lab
| Lab | What you build |
|---|---|
| Lab 01 — Transformer FLOPs, Memory & Budget Calculator | A calculator that goes from a hardware budget to a recommended (N, D) and back, with exact per-shape FLOP accounting, MoE-aware active-parameter handling, full training-memory breakdown, KV-cache sizing with GQA, and a fit-check against HBM capacity |
Success criteria. LAB_MODULE=solution pytest test_lab.py -v is green; your lab.py goes
green after the TODOs; python solution.py prints a budget report for a real cluster
configuration that you can defend line by line.
Deliverables checklist
-
I can derive
6NDwithout notes. - I can name the four places it breaks and bound the error.
-
I can compute per-step FLOPs from
(B, T, d_model, d_ff, n_heads, d_head, n_layers). - I can compute the full training memory footprint for Adam in mixed precision.
- I can compute a KV cache and show the GQA saving.
- I have run the calculator on a cluster I could plausibly be given, and written down what I would train and why.
Key takeaways
- A matmul costs
2 × (number of weights)FLOPs per token. Everything else follows. - Backward is exactly 2× forward because each forward matmul becomes two backward matmuls
(
dXanddW). 6NDexcludes attention. Fine at 2k context, badly wrong at 128k.- For MoE,
Nis active parameters. Total parameters determine memory, not FLOPs. - Memory, not FLOPs, is usually what stops you. Adam in mixed precision costs ~16 bytes per parameter before you have stored a single activation.
- The KV cache is the serving wall, and
kv_headsis the lever that moves it.