5.4.1 · D3Memory Hierarchy & Caches

Worked examples — Principle of locality (temporal - spatial)

2,444 words11 min readBack to topic

This page is the hands-on companion to the parent note on locality. There we defined the two localities. Here we compute them, one worked example per "flavour of situation" a program can throw at a cache — including the weird degenerate ones (zero reuse distance, infinite stride, random access) that the parent only mentioned in passing.

Before any numbers, let us agree on the two rulers we measure locality with. Both were introduced in the parent, but let us re-anchor them so nothing is assumed.

We will also use one derived quantity all through:


The scenario matrix

Every locality problem this chapter can ask is one of these cells. Each worked example below is tagged with the cell(s) it covers, so together they blanket the table.

Cell Access pattern Stride Reuse distance What it stresses
A Sequential sweep, stride 1 word (never reused) Pure spatial
B Same address repeated Pure temporal
C Loop over array plus an accumulator mixed mixed Both together
D Column walk of row-major matrix words (huge) large Spatial broken
E Reuse distance vs cache size boundary near Hit ↔ miss threshold
F Big block, but random / large stride large large Block-size backfire
G Degenerate: single access, empty loop undefined undefined Edge / limiting case
H Real-world word problem (image blur) 2-D mixed Applied synthesis
I Exam twist: block size doubles fixed Trade-off reasoning

Example 1 — Cell A: pure spatial locality

Forecast: Guess now — is the hit rate closer to or ?

  1. Convert the block to words. Block bytes, word bytes, so words per block. Why this step? Locality lives at the granularity of a block: one miss drags in a whole block, so counting in words tells us how many free hits ride along.
  2. Count total accesses. words touched, each exactly once (see the sweep in the figure — one blue dot per access, marching right). Why this step? We need the denominator of the hit rate.
  3. Apply the sweep formula. . Why this step? Every 16th access lands in a fresh block (a miss); the other 15 were already dragged in.
Figure — Principle of locality (temporal - spatial)
  1. Hit rate. .

Verify: blocks words words — exactly the array, no under/over-count. Hit rate per block matches the parent's . ✓


Example 2 — Cell B: pure temporal locality

Forecast: Will sum cause misses, or ?

  1. Reuse distance. Between consecutive sum accesses, zero distinct other addresses appear. So . Why this step? is the strongest possible temporal locality — the parent's rule " hit" is satisfied for any cache with .
  2. Stride. (same address every time). This is the "stride ⇒ pure temporal" cell from the parent. Why this step? Confirms there is no spatial component to explain — it is 100% temporal.
  3. Miss count. First access misses (cold), the other hit. Misses . Why this step? A block, once loaded, is never evicted because nothing competes for its slot.

Verify: Hit rate . As accesses , hit rate — the limiting behaviour of perfect temporal locality. ✓


Example 3 — Cell C: both localities at once

Forecast: More or fewer than misses?

  1. Words per block. words. (Why: same granularity argument as Ex 1.)
  2. Spatial part — array. Stride bytes word ⇒ sequential. Misses . Why this step? , and we round up — that last half-block still costs a whole miss.
  3. Temporal part — sum, i. Reuse distance (registers, no eviction) ⇒ misses. Why this step? The parent's combo example: temporal keeps hot scalars, spatial streams the array.
  4. Overall array hit rate. .

Verify: ; matches the parent's stated exactly. ✓


Example 4 — Cell D: spatial locality broken (column walk)

Forecast: Is the hit rate here closer to (like Ex 3) or near ?

  1. Address gap between rows. B[k][j] sits at &B + (k·1000 + j)·4 bytes. Stepping k → k+1 jumps bytes. Why this step? Stride is the whole diagnostic here — see the figure: consecutive accesses (red arrows) leap across entire rows.
Figure — Principle of locality (temporal - spatial)
  1. Stride vs block. Stride bytes -byte block. Each access lands in a different block. Why this step? If the jump exceeds one block, none of the neighbours we fetched will be reused.
  2. Utilisation of a fetched block. Of the 16 ints dragged in, we use : . Why this step? Quantifies "wasted bandwidth" — the parent's terrible-spatial-locality case.
  3. Misses. Effectively one miss per access ⇒ misses for column reads.

Verify: Utilisation , wasted — the mirror image of Ex 1's hit rate. See Loop blocking and tiling for the fix. ✓


Example 5 — Cell E: the reuse-distance / cache-size threshold

Forecast: Which of or still hits?

  1. Recall the rule. From the parent: hit, miss (LRU cache). Why this step? The whole point of Cell E is to sit exactly on this inequality.
  2. Case . hit. The 7 intervening blocks plus = 8 blocks, all fit. Why this step? is the least-recently-used but has not been pushed out yet.
  3. Case . miss. Eight other blocks arrived, filling all 8 slots and evicting . Why this step? Shows the razor edge: adding one more intervening block flips hit to miss.
Figure — Principle of locality (temporal - spatial)

Verify: Boolean check: (hit), (miss). The threshold is strict inequality. See Working set model. ✓


Example 6 — Cell F: bigger block backfires

Forecast: Which block size holds the whole working set?

  1. Blocks that fit — 16 B block. slots. Working set blocks ⇒ all fit, near-zero capacity misses. Why this step? Temporal locality only pays off if the reused blocks stay resident.
  2. Blocks that fit — 256 B block. slots. Working set (500 items, each in its own 256 B block because access is scattered) ⇒ constant eviction. Why this step? Fewer, fatter blocks means fewer distinct items resident — the parent's warning made numeric.
  3. Wasted bytes with 256 B block. Each fetch drags 256 B but only 16 B is wanted: used. Why this step? Random access gives no spatial payoff to offset the lost temporal capacity.

Verify: (16 B fits), (256 B thrashes). Bigger is worse here. See Cache organization fundamentals. ✓


Example 7 — Cell G: degenerate / limiting inputs

Forecast: Does a -iteration loop cause misses or ?

  1. (a) Empty loop. accesses ⇒ misses. Hit rate is undefined (), not . Why this step? Division by zero total accesses — you must say "undefined", not silently print .
  2. (b) Single access. : miss, hit rate . Reuse distance undefined (no second access). Why this step? A lone cold miss is the floor of locality — nothing to exploit yet.
  3. (c) Exact multiple, . no rounding penalty because is already an integer. Why this step? Shows the ceiling only bites when there is a remainder; here it is a clean .

Verify: ; ; . All three edge values confirmed. ✓


Example 8 — Cell H: real-world word problem (image blur)

Forecast: Good or bad locality for a horizontal sweep of the centre row?

  1. Stride along the row. Moving j → j+1 steps byte (chars are contiguous). Stride B B block. Why this step? Horizontal moves within a row are the good direction in row-major storage.
  2. Misses for one row. bytes, bytes: misses. Why this step? exactly — sweeping the row costs 30 cold block loads.
  3. Neighbour rows. Row above and below are bytes away — a different block, but each is itself swept sequentially, so they too get misses each, then reused. Why this step? The three rows of the stencil each stream well individually; the vertical gap is paid once, not per pixel.
  4. Row hit rate. .

Verify: ; hit rate . Row-major + horizontal sweep = strong spatial locality. ✓


Example 9 — Cell I: exam twist (double the block)

Forecast: Do misses halve to ~?

  1. New sweep misses. : misses. Why this step? Directly apply the sweep formula with the bigger — spatial locality improves.
  2. Compare. misses, roughly halved — good for this pure-sequential pattern. Why this step? Confirms the naive "bigger block = fewer misses" intuition when stride is 1.
  3. The hidden cost. For fixed cache size, doubling block halves the number of blocks (Ex 6's lesson) and doubles the miss penalty (twice the bytes per transfer). Why this step? The exam trap: report the win and the two costs, or you only earn half marks.

Verify: vs previous — nearly halved, exactly as claimed. ✓


Recall Quick self-test

A stride-0 access pattern has which locality? ::: Pure temporal (same address repeatedly, reuse distance 0). Reuse distance on an LRU cache with blocks — hit or miss? ::: Miss (rule is strict). Why can a bigger cache block lower the hit rate? ::: Fewer blocks fit ⇒ worse temporal capacity, plus wasted bytes when stride is large. A -iteration loop: how many misses and what hit rate? ::: misses; hit rate undefined (), not .

Related deeper dives: Cache mapping strategies · Virtual memory · Working set model · Loop blocking and tiling.