9.2Performance Optimizations

book pp. 198–199 · ~2 min read

  • migratory sharing
  • MM state
  • false sharing
  • sub-block coherence
  • coherence speculation

Decades of research have optimized coherence protocols; rather than survey it all, the book picks two optimizations that work for both snooping and directory protocols — effective, and representative of what’s possible.

9.2.1 The migratory sharing optimization

Migratory sharing is the critical-section rhythm: core after core does read-then-write on the same block (the lock variable itself is the canonical case). A plain protocol charges each hop two full transactions — a GetS it immediately regrets, then a GetM. Step through the fix:

plain MSI

C0, block BM
C1, block BI
C2, block BI

coherence transactions: 0

1 / 9The pattern

Block B holds a lock and its protected data. C0 just finished its critical section: B is M in C0. Now C1 enters — it will READ B (acquire, inspect) and then WRITE it (update, release). Then C2 will do the same. This is migratory sharing.

Two implementation routes:

Predictor only — no protocol change

A hardware table records blocks that were fetched with GetS and promptly written; on a load miss to such a block, issue a GetM instead. The hazard is misprediction: taken to the extreme (all loads issue GetM), no two cores can ever share a block read-only.

The MM state — self-correcting

MM = M for coherence purposes (dirty, exclusive, owned) plus one bit of meaning: “obtained exclusively on a predicted-migratory read.”
• Store in MM → silently M (prediction confirmed).
• Other-GetS finds M → predict migration: send an exclusive copy, invalidate self.
• Other-GetS finds MM → the store never came; pattern broken: send a shared copy, revert to S (or O). Many pure readers ⇒ everyone gets S, exactly like the plain protocol.

Migratory sharing is one detectable phenomenon; the literature holds many schemes targeting specific patterns — and general frameworks for predicting coherence events.

9.2.2 False sharing optimizations

False sharing : two cores read and write different data that happen to share a cache block. The sharing is false; the coherence traffic — permission stalls, interconnect load — is entirely real. The likelihood scales with block size (bigger blocks pack more unrelated neighbors) and depends on the workload. Two mitigations that keep the block size:

Sub-block coherence

Keep coherence state at a finer, sub-block granularity: one cache block can be M in the sub-block core 0 writes and S in the sub-block core 1 reads. Genuinely removes the false invalidations — at the cost of extra state bits per block.

Speculation

A predictor flags blocks that are invalid because of false sharing; the core then speculatively uses the stale data while the coherence permission is fetched. A correct prediction hides the latency penalty — but the requests still travel: no interconnect traffic is saved.

Check yourself

1.What is migratory sharing, and why does a plain protocol handle it badly?

2.The predictor-only approach (issue GetM instead of GetS on a predicted-migratory load miss) needs no protocol change. What's its danger?

3.A cache holds a block in MM and receives another core's GetS. A cache holds the same block in M and receives a GetS. What's the difference in response?

4.What is false sharing, and which design parameter most directly affects it?

5.Compare the two false-sharing mitigations: what does each cost or fail to fix?

5 questions