Chapter 28 — Instructor Notes
Teaching Notes
Why this chapter matters and where it sits. It is the hinge of Part VII: Chapter 27 argued why Fortran is fast; this chapter teaches students to measure it on their own code; Chapter 29 then optimizes what they found. The single behavioural goal is to break the reflex to optimize by intuition. Every professional has the "week on the 2% routine" scar — tell that story on day one and keep returning to it. If students leave able to profile before they optimize, the chapter succeeded, even if they forget a flag.
The three ideas to emphasize, in order:
1. Measure, don't guess. Human intuition about where time goes is reliably wrong. The profiler is not for
emergencies; it is the first step. Pike's Rule 2 is the whole chapter.
2. The system_clock idiom, exactly right. This is the one piece of code they must get perfect:
int64 counters, read count_rate, subtract, divide, mind the wrap. It is a five-minute topic that
students get wrong for years otherwise. Drill it.
3. Memory-bound vs compute-bound. The threshold concept: for array kernels the bottleneck is usually the
memory, not the math. Arithmetic intensity ($< 1$ flop/byte ⇒ memory-bound) is the tool. This is what
makes Chapter 29's "loop order and blocking, not fewer multiplies" make sense.
Misconceptions to preempt:
- "Optimize the routine that looks slow / interesting." No — profile first. Case Study 1 is built entirely
to demolish this; assign it early.
- "cpu_time and system_clock are the same." They measure different quantities. The wall-vs-CPU table is
a free diagnostic; make them memorize "wall $\gg$ CPU ⇒ waiting."
- "Profile the debug build so I can see everything." The -O0 build has the wrong balance and phantom hot
helpers that -O2 inlines away. Profile what you ship.
- "count_rate is 1000 / a million / a billion." It is whatever the call returns — READ it. The negative-
time bug (B5, CS-01) comes from guessing it and from default-integer wrap.
- "The stencil is compute-bound because it does arithmetic." It is memory-bound ($I \approx 0.4$). The
"add a flop, no slowdown" experiment (C9) is the visceral proof.
- "One run is a benchmark." It is an anecdote. Warm up, repeat, report min/median + spread.
- "My fast benchmark result is real." Maybe the compiler deleted the loop (E18). Consume the result.
A note on honesty (important for this chapter specifically). The book never runs code, so every timing
number, gprof output, and cachegrind summary in the text is CONSTRUCTED and labelled "representative." Tell
students this openly and turn it into the lesson: your numbers will differ, and that is the point — compare
ratios and shapes, trust your own machine. The system_clock/cpu_time/timers code is exact and
compilable; only the times are illustrative. Model the discipline you are teaching.
Live-coding demo (25–30 min). Do the measuring live — this is the one chapter where running is the lesson.
1. Type the system_clock idiom from scratch; deliberately first write it with default integer and a
hard-coded /1000.0, run it, and show a garbage/negative time. Then fix it to int64 + read the rate.
The before/after is the whole of §28.1.
2. Take the heat-solver project-checkpoint.f90. Compile -O2 -pg -g, run, gprof. Read the flat profile
live and let the class predict which routine dominates before you scroll to it. It is laplacian (~78%)
— confirming, not surprising, which is the point.
3. If time and a Linux box: valgrind --tool=cachegrind on the good vs bad stencil loop order and read the
D1 miss rates. Watching the miss rate triple with a one-line loop swap is the memory-bound "aha."
NOTE: the book's representative numbers are for the page; in class you obviously run it and get real numbers.
Hand-verify the 5×5 sanity block (28,32,28) on the board first so students trust the instrumented solver.
Time budget (≈ 5 h, matching the estimate): - §28.1 timers + wall/CPU + the idiom drill — 60 min (do the live before/after here) - §28.2 gprof workflow + reading flat profile & call graph — 60 min - §28.3 hot loop + memory/compute-bound + arithmetic intensity — 60 min (the conceptual heart) - §28.4 cachegrind demo — 45 min - §28.5 methodology + the 80/20 arithmetic — 45 min - Project Checkpoint + Case Study 1 — 30 min in class, rest as homework
Prerequisites to review before teaching: Ch. 6 (pure, intent, the frozen step), Ch. 27 (column-
major loop order, no-aliasing — this chapter measures exactly that), Ch. 24 (the solver/stencil being
profiled), Ch. 13 (valgrind, so cachegrind is "a new tool of a familiar suite"). A 10-minute warm-up recalling
Ch. 27's "loop order can be 10×" claim is the ideal on-ramp: this chapter proves it with cachegrind.
Assessment tip. The best single exam prompt is Case Study 1's scenario: "A team made routine X three times faster and the whole program sped up 3%. Here is the flat profile. Explain the 3%, and say what they should have optimized." It tests the flat profile, the 80/20 arithmetic ($S = 1/((1-p)+p/K)$), and the measure-first discipline in one realistic problem. A close second: "Here is a homemade timer that prints negative numbers — find all three bugs" (B5).