5.4.14 · D4Memory Hierarchy & Caches

Exercises — Cache coherence problem

2,545 words12 min readBack to topic

This page is a self-test ladder for the Cache Coherence Problem. Work each problem before opening its solution. Difficulty climbs L1 Recognition → L2 Application → L3 Analysis → L4 Synthesis → L5 Mastery. Every solution is complete, so you can grade yourself.

Two words we lean on throughout, defined once so no symbol is unearned:


Level 1 — Recognition

Exercise 1.1

State, in one sentence, what the cache coherence problem is.

Recall Solution

When multiple private caches hold copies of the same memory address, a write by one core can leave the other caches (and possibly main memory) holding stale values, so different cores read different numbers for the same address.

Exercise 1.2

Which of these is a coherence concern and which is a consistency concern? (a) All cores must observe writes to address X in the same order. (b) The allowed orderings of operations across different addresses X and Y.

Recall Solution
  • (a) is coherence — it is about a single address across caches (this is the write-serialization rule).
  • (b) is consistency — it is about ordering across different addresses. See Memory Consistency Models for (b). Coherence = what value; consistency = when/what order across locations.

Exercise 1.3

True or False: "Write-through caches make main memory always fresh, therefore they solve cache coherence."

Recall Solution

False. Write-through keeps memory fresh, but it does not touch another core's cache. That other cache can still return its own stale copy. Write-through closes the memory-vs-cache gap; coherence is the cache-vs-cache gap. See Write-through vs Write-back.


Level 2 — Application

Exercise 2.1

Setup: X = 5 in memory. Both Core A and Core B use write-back caches, no coherence protocol. Trace the copies:

  1. A reads X, 2. B reads X, 3. A writes X = 20, 4. B reads X.

Fill in Cache A, Cache B, Memory after each step, and state what B reads at step 4.

Recall Solution

Figure — Cache coherence problem

Step Cache A Cache B Memory
1 A reads X=5 X=5
2 B reads X=5 X=5 X=5
3 A writes 20 X=20 X=5 ❌ X=5 ❌
4 B reads X=20 X=5 (stale) X=5

B reads 5. This is wrong; the true value is 20. Memory is also still 5 because write-back has not flushed A's dirty line yet. Two independent bugs — cache-vs-cache and memory-vs-cache.

Exercise 2.2

Now repeat Exercise 2.1 but with a write-invalidate protocol. What happens at step 3 and what does B read at step 4?

Recall Solution

Figure — Cache coherence problem

  • Step 3: A writes X=20 → A broadcasts an invalidate → Cache B marks its X copy Invalid.
  • Step 4: B reads X → its copy is Invalid → this is a forced miss → B fetches the fresh value → gets 20. ✅

The invalidate converted B's silent staleness into a loud miss, and the miss is exactly what pulls the correct value. See MESI Protocol.

Exercise 2.3

Under write-update (broadcast), what does B's cache hold immediately after step 3, and does B's step-4 read cause a miss?

Recall Solution
  • After step 3, A broadcasts the new value 20; B's copy is updated in place to X=20 (still valid).
  • Step 4 read is a hit returning 20 — no miss. ✅

Update spends a broadcast at write time to save the reader a miss later. Whether that trade wins depends on the sharing pattern (next level).


Level 3 — Analysis

Exercise 3.1

Core A writes X four times in a row, then Core B (a single other sharer) reads X once. Count bus events for write-invalidate vs write-update. (An "event" = one invalidate broadcast, one update broadcast, or one read miss serviced.)

Recall Solution

Write-invalidate:

  • Write 1: A does not yet own the line exclusively → 1 invalidate to knock out B. Now A has exclusive ownership.
  • Writes 2, 3, 4: A already owns it exclusively → 0 events each.
  • B's read: B's copy is invalid → 1 read miss.
  • Total events.

Write-update:

  • Writes 1–4: each pushes the new value to B → 4 update broadcasts.
  • B's read: copy already fresh → 0.
  • Total events.

Invalidate wins 2 vs 4. Repeated writes by one core to one line is the killer case for update.

Exercise 3.2

Now the reverse pattern: A writes X once, then B reads X five times back-to-back (with no further writes). Count bus events for each protocol.

Recall Solution

Write-update:

  • Write: 1 update broadcast (B's copy now fresh).
  • Reads 1–5: all hits0 events.
  • Total .

Write-invalidate:

  • Write: 1 invalidate.
  • Read 1: B's copy invalid → 1 miss (fetches fresh 20; now valid again).
  • Reads 2–5: hits → 0.
  • Total .

Update wins 1 vs 2. When a reader needs the value right after each write, update dodges the miss.

Exercise 3.3

Derive the coherence invariant that a write violates, then state the two ways to restore it.

Recall Solution

Invariant we want — any two cores that both think their copy is valid must agree: A write on core performs , changing only 's copy. If some other valid copy existed with the old value, the two sides of the equation now differ — invariant broken.

Two repairs (eliminate the stale valid copy):


Level 4 — Synthesis

Exercise 4.1

You are given a workload mix. For each pattern, pick invalidate or update and justify in one line. (a) A lock/flag written many times by one core between reads. (b) A tight producer/consumer where B consumes each value A produces exactly once, immediately. (c) A widely-shared read-mostly config value that A rewrites once per hour.

Recall Solution
  • (a) Invalidate. Many writes by one owner → after the first invalidate the writer owns the line and later writes are free. Update would broadcast every write.
  • (b) Update. One write then an immediate read each cycle → update keeps B's copy fresh and avoids the read miss (Exercise 3.2 logic).
  • (c) Either is cheap, invalidate preferred. One write per hour is negligible traffic; with many sharers, an update would broadcast to all of them, while invalidate sends one invalidation and lets sharers re-fetch lazily only if they still care.

Exercise 4.2

A cache line holds two independent variables X (used only by A) and Y (used only by B), packed into the same line. A writes X repeatedly; B writes Y repeatedly. Under write-invalidate, what pathology occurs and what is it called?

Recall Solution

Each time A writes X it invalidates B's copy of the whole line (coherence tracks lines, not individual variables), so B's next access to Y misses and re-fetches. Then B writes Y and invalidates A's line, forcing A to re-fetch to touch X. The line "ping-pongs" between the caches although the cores never share real data.

This is ==false sharing==. The fix is to place X and Y on different cache lines (padding/alignment). See False Sharing.

Exercise 4.3

Explain why a snooping bus protocol struggles as core count grows, and what alternative scales better.

Recall Solution

In snooping, every cache listens to a shared broadcast medium; each coherence action (invalidate/update/miss) is seen by all caches. Bus bandwidth is fixed, so as cores increase, total broadcast traffic grows and the single bus saturates — a scalability wall (see Bus Traffic & Scalability).

The alternative is a directory protocol: a directory records which caches hold each line, so a write sends messages only to the actual sharers (point-to-point over a scalable interconnect) instead of broadcasting to everyone. See Snooping vs Directory Coherence.


Level 5 — Mastery

Exercise 5.1

Design decision. A 32-core server runs a workload that is 90% single-writer bursts (one core hammers a line, others rarely read) with occasional wide sharing. Choose a coherence design end-to-end: invalidate vs update, snoop vs directory. Justify each choice with the exercises above.

Recall Solution
  • Write-invalidate, because the dominant pattern is single-writer bursts. Exercise 3.1 showed invalidate collapses N writes to 1 event; update would pay N broadcasts. Overwhelmingly the right base policy.
  • Directory-based, because 32 cores on a shared broadcast bus would saturate (Exercise 4.3). A directory sends invalidations only to actual sharers over a point-to-point interconnect, scaling with sharing degree, not core count.
  • Net: an invalidate + directory design (the shape of real many-core coherence). It pairs the cheap-burst policy with the scalable delivery mechanism.

Exercise 5.2

Full trace + count. Three cores A, B, C. Line starts uncached, X=5, write-invalidate protocol. Events: (1) A reads, (2) B reads, (3) C reads, (4) A writes X=9, (5) B reads, (6) C reads. List each event's outcome and total bus events (miss or invalidate = 1 event each).

Recall Solution
  • (1) A reads → miss, fetch → A valid. (1)
  • (2) B reads → miss, fetch → A,B valid. (1)
  • (3) C reads → miss, fetch → A,B,C valid (shared). (1)
  • (4) A writes 9 → 1 invalidate broadcast → B and C both marked Invalid; A now exclusive/modified. (1)
  • (5) B reads → copy invalid → miss, fetch fresh 9 (A supplies) → B valid, holds 9. (1)
  • (6) C reads → copy invalid → miss, fetch fresh 9 → C valid, holds 9. (1)

Total bus events. Note: one invalidate covered both sharers (single broadcast on a snoop bus); the two later read misses are the price of having invalidated them.

Exercise 5.3

Prove the three coherence conditions each fail in a "no-protocol write-back" system by giving a one-line counterexample for each.

Recall Solution

Let X=5, A and B both cache it.

  • Program order (self-read): A writes 7 to its cache; if A's cache silently evicts and a later A-read misses to stale memory (still 5), A fails to read its own write. Violated without write propagation to memory.
  • Write propagation: A writes 7; B keeps reading its cached 5 forever — A's write is never seen by B. Violated.
  • Write serialization: A writes 7, B writes 8, with no serializing point, C may observe 7-then-8 while D observes 8-then-7. Violated — no agreed global order for that line. Each condition is exactly the guarantee a coherence protocol restores.