Calibration — Before Week One
A 3-hour battery, taken cold, that sizes the first three projects to you rather than to my guess about you.
Without it, P01's eight weeks assume a starting point I invented. If attention is already second nature, weeks 1–4 are waste. If Rust ownership defeats you in P11-I, the whole Stage-2 schedule is wrong and you discover it in month five.
This is not a test you can fail. Every outcome maps to a schedule, and the "you already know this" outcomes save you more time than the "you need longer" outcomes cost.
Table of Contents
- Rules
- The Five Tasks
- C1 — Attention, From the Description
- C2 — Nearest Neighbour, Naive to Better
- C3 — Systems Arithmetic
- C4 — Ownership and Lifetime
- C5 — Measurement Judgement
- Scoring
- What Your Scores Change
- Re-Calibration
- References
Rules
| Time | 3 hours 10 minutes, timed per task. Stop when the timer stops, mid-line if necessary |
| Tools | Language reference and standard-library docs only. No search, no assistant, no papers, no prior code of yours |
| Cold | Do not read the project pages first. If you have already read P01, note that and discount C1 accordingly |
| Honesty | Nobody sees this. A contaminated calibration produces a plan for a person who does not exist — which is the exact failure the sibling track's locked PLAN.md exists to prevent |
| Record | Write answers in notebook/000-calibration.md as you go, including where you got stuck and what you tried |
Take it in one sitting. Split across days it measures your best day rather than your working level.
The Five Tasks
| # | Task | Minutes | Sizes | Measures |
|---|---|---|---|---|
| C1 | Attention, from the description | 45 | P01 | Can you turn a specification into correct tensor code? |
| C2 | Nearest neighbour, naive to better | 40 | P02 | Algorithmic instinct + do you reach for measurement? |
| C3 | Systems arithmetic | 25 | P04, P05, P14 | Back-of-envelope fluency — the skill the whole track rests on |
| C4 | Ownership and lifetime | 40 | P11-I, P04, P12 | Rust readiness, which is the journey's one real language cost |
| C5 | Measurement judgement | 30 | Everything | Can you spot a lying benchmark? |
| Scoring and mapping | 20 |
C1 — Attention, From the Description
45 minutes. No reference to any Transformer material.
Here is a specification with no code and no formula. Implement it.
You have \(T\) vectors \(x_1 \dots x_T\), each of dimension \(d\), as a matrix
Xof shape(T, d).Produce an output
Yof the same shape, where each output row \(y_i\) is a weighted average of transformed input rows \(1 \dots i\) — never rows after \(i\).The weights must depend on the content of the rows, not their positions: row \(i\) decides how much attention to pay to row \(j\) by comparing a vector derived from \(x_i\) against a vector derived from \(x_j\). The weights over \(j\) must be non-negative and sum to 1.
The number of learnable parameters must not depend on \(T\).
Deliverables, in this order:
- The mechanism in words, before any code. What are the learnable parameters and what are their shapes?
- A numpy implementation,
attention(X, Wq, Wk, Wv) -> Y. - A test that the weights sum to 1 for every row.
- A test that row \(i\) is unaffected by any change to rows \(> i\).
- Its computational cost in FLOPs, as a function of \(T\) and \(d\).
Self-score after time is up:
| 1 | Could not produce a mechanism that satisfies the constraints |
| 2 | Mechanism roughly right; code incomplete or the masking is wrong |
| 3 | Working implementation, both tests pass |
| 4 | + correct FLOP count, and you scaled the scores by something (even if you were unsure why) |
| 5 | + you can state why the scaling is needed in terms of the variance of a dot product, and you noticed the parameter count is independent of \(T\) by construction |
What separates 3 from 5 is not implementation skill; it is whether the arbitrary constants prompt a question. That is exactly the habit P01 exists to build, so a 3 here is a good reason to do P01 in full.
C2 — Nearest Neighbour, Naive to Better
40 minutes.
You have 100,000 vectors of dimension 128 in memory, and a stream of query vectors. For each query, return the 10 most similar by cosine similarity.
- Write the exact solution. (10 min)
- Estimate its per-query cost — arithmetic operations and bytes moved — before running it. Write the estimate down, then measure. (10 min)
- Without looking anything up, propose two ways to make it sub-linear, and for each state precisely what you give up. (15 min)
- For one of them, state the experiment that would tell you whether it works, and what result would make you abandon it. (5 min)
Self-score:
| 1 | Exact solution only; no cost estimate |
| 2 | Exact solution + a cost estimate that was off by >10× |
| 3 | Cost estimate within ~3×; one plausible sub-linear idea |
| 4 | + two ideas with the trade-off named for each (recall, memory, build time) |
| 5 | + a falsifiable experiment with a stated falsifier, and you noticed that normalising makes cosine, dot product and L2 give identical rankings |
Step 2 is the one that matters. The habit of estimating before measuring is what the whole notebook is built around, and it is independent of whether you have seen ANN search before.
C3 — Systems Arithmetic
25 minutes. Pen and paper. No calculator beyond arithmetic.
Eight questions. Order-of-magnitude answers are fine; state your assumptions, which matter more than the number.
- A service handles 10,000 requests/second at 50 ms mean latency. How many requests are in flight on average?
- Your process reads 4 KB from a file 100,000 times. The data is in the OS page cache. Roughly how long does the syscall overhead alone take?
- A 7-billion-parameter model in bf16 generates one token. How many bytes must move from memory, at minimum? At 2 TB/s, how long is that?
- A key-value store does one
fsyncper write. What write rate can it sustain, to within an order of magnitude? - An LSM tree with fanout 10 holds 64 GB with a 64 MB first level. Roughly how many levels, and how many times is a byte rewritten under leveled compaction?
- A request fans out to 50 services, each exceeding its p99 latency 1% of the time. What fraction of requests are slow?
- A 512×512 fp32 matrix multiply. How many FLOPs? At 20 GFLOP/s, how long?
- You want to detect a 1% relative change in a metric with standard deviation equal to its mean. Order of magnitude of users per arm?
Answers with the reasoning are in the numbers reference — but score yourself before looking:
Expected answers (open only after you have written yours)
- 500. Little's Law: \(L = \lambda W = 10^4 \times 0.05\).
- ~13 ms. 100,000 × ~128 ns. Note the data is nearly free from cache; the boundary crossing is the cost.
- 14 GB (7e9 × 2 bytes), ~7 ms. Every weight is read once per token.
- ~10⁴ writes/s. fsync is ~100 µs. This is the ceiling regardless of everything else.
- 3 levels beyond the base (\(\log_{10}(64\text{GB}/64\text{MB}) = 3\)); write amplification ≈ \(10 \times 3 + 1 \approx 31\).
- ~39%. \(1 - 0.99^{50}\).
- 268 MFLOP (\(2N^3\)); ~13 ms.
- ~10⁵ per arm. \(n \approx 16\sigma^2/\delta^2\) with \(\sigma/\mu = 1\) and \(\delta/\mu = 0.01\) gives \(16/10^{-4} = 1.6\times10^5\).
Self-score: 1 = 0–2 correct to an order of magnitude · 3 = 4–5 correct · 5 = 7–8 correct with assumptions stated.
This is the highest-signal task in the battery. Every project in the track opens with a prediction, and back-of-envelope fluency is what makes predictions worth writing down.
C4 — Ownership and Lifetime
40 minutes. Rust if you have it installed; otherwise answer in prose and C.
Implement a scope chain: an
Environmentwith a map from name to value and an optional parent. Supportget(searching up the chain) anddefine.Then: a
Closureholds a function body and a reference to the environment where it was created. Two closures created in the same scope must see each other's writes to that scope.
- Write the type definitions. (15 min)
- Implement
getanddefine. (15 min)- Answer in writing: what keeps the environment alive after the function that created it returns? What happens if two closures both mutate the same variable? (10 min)
Self-score:
| 1 | Could not express the shared-mutable-parent structure at all |
| 2 | Wrote it in a GC language and could not say what the Rust/C version needs |
| 3 | Correct structure; needed to look up the exact smart-pointer syntax |
| 4 | + can explain why Rc<RefCell<>> (or manual refcounting in C) is required — shared ownership plus interior mutability |
| 5 | + can state what a cycle would do to it, and that this is why tracing GC exists |
A 1 or 2 is the single most schedule-relevant result in the battery, because Rust is the journey's one real language cost and P11-I is where it is paid.
C5 — Measurement Judgement
30 minutes. Five benchmarks. For each: what is wrong, and what would you measure instead? Roughly 6 minutes each.
B1. To measure syscall cost:
t0 = now(); for (i=0;i<1e7;i++) getpid(); t1 = now();
printf("syscall: %.2f ns\n", (t1-t0)/1e7*1e9); // prints 1.23 ns
B2. To measure DRAM latency, a pointer chase where each pointer points 64 bytes ahead, wrapping at the end of a 512 MB buffer. Reports 1.3 ns per load.
B3. To compare two sorting functions:
t0=time.time(); sort_a(data); t1=time.time()
t2=time.time(); sort_b(data); t3=time.time()
print(f"b is {(t1-t0)/(t3-t2):.2f}x faster") # prints 1.04x faster
B4. A load generator sends a request, waits for the response, then sends the next. Under a 1-second server stall it reports p99 = 12 ms.
B5. A Bloom filter at 24 bits/key is tested with 200,000 absent keys. Zero false positives observed. Reported as "false-positive rate: 0%, better than the predicted 1e-5".
What each one is (open after answering)
- B1 —
getpid()is cached by libc; this is not a syscall. It is four times an empty loop iteration, which is impossible for a mode switch. Use a syscall that must trap and fails fast, e.g.close(-1). - B2 — a constant 64-byte stride is exactly sequential cache lines and the prefetcher hides the whole latency. Use a random single cycle (Sattolo).
- B3 — one run each, no warmup, no repetition, no uncertainty. A 4% difference from two samples is noise. Repeat, report p50/p95/p99, bootstrap the median, and be willing to say "no measurable difference".
- B4 — coordinated omission. The generator stopped sending during the stall, so it never recorded the latencies its own stall caused. Send on a schedule and measure from intended send time.
- B5 — no resolution. At 1e-5, 200k probes expect ~2 events; observing 0 is Poisson noise, not a result. You need ~100/p ≈ 10 million probes.
Self-score: 1 = spotted 0–1 · 3 = spotted 3 · 5 = spotted all five and named the correct replacement measurement for each.
Every one of these is a mistake made and documented during the construction of this track (§14). Spotting them cold is genuinely hard, and a low score here is the least worrying of the five — it is the most teachable.
Scoring
Record in notebook/000-calibration.md:
C1 attention _/5
C2 nearest neighbour _/5
C3 systems arithmetic _/5 <- highest signal
C4 ownership _/5 <- most schedule-relevant
C5 measurement _/5
___
total _/25
Then run:
cd tools && python3 calibrate.py C1 C2 C3 C4 C5 # e.g. python3 calibrate.py 3 4 2 1 3
It prints the adjusted schedule and the total delta in weeks.
What Your Scores Change
| Task | Score | Adjustment |
|---|---|---|
| C1 | 1–2 | P01 as written, 8 weeks. Add the extra reading in week 2 |
| 3 | P01 as written, 8 weeks | |
| 4 | P01 −1 week: compress milestones 3–4 (single head + masking) into one | |
| 5 | P01 −2 weeks: start at milestone 5; keep every experiment. Never skip the experiments — they are the project, the implementation is the substrate | |
| C2 | 1–2 | P02 as written, 7 weeks. Do math.md §concentration before week 1, not week 9 |
| 3–4 | P02 as written, 7 weeks | |
| 5 | P02 −1 week: fold milestones 3–4 together | |
| C3 | 1–2 | +1 week before Stage 1: work through numbers.md §§1–5 and 9–11, redoing every derivation on paper. This is the highest-return week in the whole plan for you |
| 3 | Re-take C3 at the M7 stage review | |
| 4–5 | No change. You already have the skill the track is trying to build | |
| C4 | 1–2 | P11-I +2 weeks (5→7). Do the Rust book chapters 4, 10, 15 before the project rather than during. Consider moving P11-I earlier still, to week 9, so Rust has longer to settle before P04 |
| 3 | P11-I as written, 5 weeks | |
| 4–5 | P11-I −1 week. Consider C for P12 instead of Rust, since Rust buys you less | |
| C5 | 1–2 | Read numbers.md §14 and the bench.py preamble in week 1, and re-take C5 at M7 |
| 3–4 | No change | |
| 5 | No change. Consider a higher bar on your own benchmark-quality scores |
Totals
| Total | Reading |
|---|---|
| 5–10 | The 34-month plan is right, and the extra weeks above are well spent. Do not compress anything |
| 11–17 | The plan as written fits you. Apply only the per-task adjustments |
| 18–22 | You are ahead. Take the per-task reductions, and raise your scorecard bar — a 3 for you should be someone else's 4 |
| 23–25 | Stage 1 is largely revision. Consider: P01 and P02 at MVI scope with the full experiment suite, then jump to Stage 2 and reinvest the ~6 saved weeks in P05 or P15 — the two projects most likely to overrun |
A high score does not mean skip the experiments. Every reduction above cuts implementation weeks. The experiments, the notebook entries and the reports are the part that builds the capability you asked for, and they are never the thing to cut.
Re-Calibration
Re-take C3 and C5 at each stage review — M7, M15, M22, M26, M31. Both are 25–30 minutes and both measure skills the track claims to build, so a flat score across two stages is evidence the program is not working for you and something needs to change.
C1, C2 and C4 do not repeat well: once you have built the thing they ask about, they measure memory rather than aptitude.
Record each re-take alongside the first in notebook/000-calibration.md so the
trajectory is visible. Along with the scorecard trend,
that is the only objective evidence you will have that 34 months of evenings changed
something.
References
- Ericsson, K. A. et al. The Role of Deliberate Practice in the Acquisition of Expert Performance. Psychological Review 100(3), 1993. Practice must target the edge of current ability; a plan not sized to the learner is not deliberate practice.
- Vygotsky, L. S. Mind in Society. Harvard University Press, 1978. The zone of proximal development — the argument for calibrating difficulty rather than fixing it.
- Bjork, R. A., Bjork, E. L. Desirable Difficulties in Theory and Practice. JARMAC 9(4), 2020. Why the correct adjustment for a high scorer is less scaffolding, not less work.
- Kruger, J., Dunning, D. Unskilled and Unaware of It. JPSP 77(6), 1999. Self-assessment is least reliable at the low end, which is why every task here has concrete 1/3/5 anchors rather than asking how confident you feel.
- Wiggins, G., McTighe, J. Understanding by Design, 2nd ed. ASCD, 2005. Diagnostic assessment that feeds directly into instructional design, which is what the adjustment table is.