Skip to content

Multiprocessors ​

When one core isn't enough, we use many. This chapter covers Flynn's taxonomy, shared vs distributed memory (UMA/NUMA), cache coherence (MSI/MESI snooping and directories), synchronization primitives (locks), and the crucial distinction between coherence and consistency.

Taxonomy (Flynn) ​

ClassMeaningStatus
SISDsingle instruction, single datauniprocessor
SIMDsingle instruction, multiple datavector architectures (less flexible)
MISDmultiple instruction, single datano commercial multiprocessor
MIMDmultiple instruction, multiple datamost modern multiprocessors (most flexible)

MIMD dominates because off-the-shelf cores are easy to replicate and it adapts to any workload.

Memory organization ​

Centralized shared memory (SMP / UMA) ​

  • Multiple processors attached to a single centralized memory.
  • All processors see the same memory organization → Uniform Memory Access (UMA).
  • "Shared-memory" = all processors can address the full address space.
  • Bandwidth bottleneck? Only if caches are small and you exceed ~a dozen processors. Large caches make SMP practical.

Distributed memory (NUMA) ​

  • Each node has its own memory → Non-Uniform Memory Access (NUMA): local memory is fast, remote memory is slow.
  • Scales to many more nodes than a centralized bus allows.
SMP:   P1..Pn -- bus -- Memory        (UMA)
NUMA:  Node(P,M)--net--Node(P,M)       (local fast, remote slow)

Cache coherence ​

Problem: with private caches, a block can have multiple copies that diverge. Protocols keep caches consistent so a processor reading a location sees the latest write.

Snooping-based (MSI / MESI) ​

Each block has a state; a write goes on the bus and sharers invalidate their copies.

StateMeaning
I (Invalid)not present / stale
S (Shared)clean copy(ies), read-only permission
M (Modified)dirty, only valid copy, memory stale
E (Exclusive, MESI)clean, only copy, can write without broadcast
  • MSI: Invalid, Shared, Modified.
  • MESI adds Exclusive — a clean sole copy, so a write doesn't need a bus upgrade (avoids a broadcast for the common write-to-private-block case).

Worked example (MSI flow) ​

  • P1 Rd X: miss → bus → memory responds → X in cache-1 S.
  • P2 Rd X: miss → bus → memory responds → X in cache-2 S (cache-1 does nothing on a read).
  • P1 Wr X: has S (read-only) → bus upgrade → cache-2 invalidates → cache-1 → M.
  • P2 Rd X: cache-2 I → bus → cache-1 snoops, downgrades to S, supplies data, memory updated → cache-2 S.

A full 4-processor trace (Problem from slides) shows the state machine evolving across Rd X, Rd X, Wr X, Wr X (P3 responds since it holds M), Rd X (P3 responds + mem writeback), Rd X (P3 + P4 both S). The protocol guarantees every read eventually sees the latest write.

Directory-based ​

A directory tracks each block's sharers (a presence bit-vector), avoiding broadcast.

  • States: Uncached, Shared (≥1 have it, memory up-to-date), Exclusive (one owner, memory stale).
  • Read by processor i: if dirty=0, read from memory, set p[i]=1; if dirty=1, recall from owner, set SHARED, update memory, dirty=0, set p[i]=1, supply data.
  • Write by processor i: if dirty=0, supply data, send invalidations to all sharers, dirty=1, p[i]=1.
  • Scales better than snooping (no broadcast bus); used in large NUMA systems.

Write policies ​

  • Write-invalidate: gain exclusive access, invalidate others (common; used above).
  • Write-update: broadcast the new value to sharers (more bandwidth, fewer subsequent misses for readers).

Synchronization ​

Critical sections must execute atomically. The hardware provides a basic primitive: atomic read-modify-write.

  • Atomic exchange: swap register ↔ memory.
  • Test & set: read location into register, write 1 (lock free if was 0).
  • Lock / unlock pattern:
mips
lock:  t&s  register, location   # atomic: reg = mem; mem = 1
       bnz  register, lock       # spin until we got the 0
       # ---- critical section ----
       st   location, #0         # release

When multiple threads run this, only one observes the 0 and enters the critical section; the rest spin until the owner stores 0.

Why locks matter (bank example) ​

Two parallel transactions on a $1000 balance, each Rd; Add $100/$200; Wr, without a lock → both read 1000, both write 1100/1200 → lost update. A lock serializes them → correct $1300.

Coherence vs consistency ​

  • Coherence guarantees:
    1. Write propagation — a write eventually becomes visible to other processors.
    2. Write serialization — all processors see writes to one location in the same order.
  • Consistency defines the ordering of accesses to different locations. It tells the programmer what reorderings the hardware may perform, so they can write correct parallel code.

Consistency example (the race) ​

Initially A = B = 0
P1:                P2:
  A <- 1             B <- 1
  if (B == 0)        if (A == 0)
    Crit.Sect.         Crit.Sect.

The programmer hoped this implements a lock: if both ifs passed, both would have written before reading the other's flag. But with out-of-order execution and weak consistency, both processors can enter the critical section. Coherent caches don't save you — coherence only orders accesses to the same location, not the cross-variable ordering the algorithm needs. The consistency model defines what reorderings are allowed, and disciplined mutual exclusion (real locks) is what makes such code safe.

Sequential consistency ​

A multiprocessor is sequentially consistent if the result is achievable by:

  • maintaining program order within each processor, and
  • interleaving accesses across processors in an arbitrary fashion.

The example above is not sequentially consistent. To implement it you need: program order + write serialization + everyone sees an update before a read. This is intuitive but extremely slow (blocks many performance optimizations).

Relaxed consistency ​

Sequential consistency is too slow for high performance. The complication arises only with race conditions (two threads on shared data, ≥1 writing). If programmers enforce mutual exclusion around shared data, the hardware can safely allow some reorderings → relaxed consistency balances performance and programming effort. Examples: allowing store→load reordering, or reads to pass writes, with explicit fence/barrier instructions where ordering matters.

Summary table ​

TopicKey idea
FlynnMIMD is the practical multiprocessor class
SMP/NUMAUMA (shared bus) vs NUMA (distributed, non-uniform)
CoherenceMSI/MESI snooping or directory; keep copies consistent
MESIadds Exclusive to avoid write-upgrade broadcast
Directorypresence vector; scales without broadcast
Syncatomic RMW (exchange, test&set) builds locks
Coherence vs consistencysame-location order vs cross-location order
SC vs relaxedintuitive but slow vs fast but needs disciplined locking

MESI state transitions (explicit) ​

The four MESI states and their key transitions:

From → ToTrigger
I → Eprocessor reads a block no one else has → gets exclusive clean copy
I → Sprocessor reads a block others also have → shared
E → Mprocessor writes its sole clean copy → becomes dirty (no broadcast needed)
S → Mprocessor writes a shared block → broadcasts invalidate, becomes M
M → Sanother processor reads → owner downgrades to S, supplies data, memory updated
M → Ianother processor writes → owner invalidates (its dirty data may be written back)
S → Ia write by another processor invalidates my shared copy

The Exclusive state is the key optimization: a write to an E block needs no bus transaction, whereas an S block must broadcast an upgrade.

Consistency model spectrum ​

Beyond sequential vs relaxed, real ISAs define specific orderings:

ModelAllowsNotes
Sequential (SC)nothing reordered across processorsintuitive, slow
Total Store Order (TSO)store→load reorderingcommon on x86
Release Consistencyacquire/release fences separate sync from ordinary accessesneeds explicit locks/barriers

Programmers reason about these via fences/barriers: a lock acquire is a one-way barrier, a release another; ordinary loads/stores between them may be freely reordered by the hardware, which is what delivers the performance.

False sharing ​

Two processors write different variables that happen to sit in the same cache block. Coherence forces the block to bounce between caches (M→I→M) even though no true sharing occurs → severe slowdown. Fix: pad/align frequently-written per-thread data to separate cache lines (typically 64 B).

Key takeaways ​

  • Coherence keeps one location's copies consistent (propagation + serialization).
  • MESI's Exclusive state avoids needless broadcasts; directories scale via presence vectors.
  • Locks built from atomic primitives; out-of-order + weak consistency can break naive "locks" → use real mutual exclusion.
  • Sequential consistency is the easy-to-reason model but slow; relaxed models win performance when programmers use locks/barriers correctly.

This is the final chapter — together with Chapters 1–10 it covers the full CS1541 arc: from why architecture matters, through pipelining/ILP/OoO, caches/virtual memory/DRAM, to multiprocessor coherence and security.