Simple Answers & Key Points · 23 Questions
The Memory Hierarchy is a fundamental architectural concept that organizes storage into multiple levels, each offering a different balance of speed, size, and cost. It exists because no single memory technology can simultaneously satisfy all three requirements of an ideal memory: fast, large, and cheap.
The Core Problem (The Speed-Size-Cost Triangle):
The Solution — Memory Hierarchy:
By placing small amounts of fast, expensive memory (registers, L1/L2/L3 caches) close to the CPU and progressively larger, slower, cheaper memory (DRAM, SSD, HDD) farther away, the system creates the illusion of a single memory that is both as fast as SRAM and as large as a hard disk. This illusion works because of the Principle of Locality — programs tend to access only a small fraction of memory at any given time, and that fraction can be kept in the fastest cache layer.
The Hierarchy Levels (Fastest to Slowest):
The Principle of Locality is the empirical observation that programs do not access all memory locations with equal probability. Instead, they tend to access a small, concentrated subset of addresses at any point in time. This principle provides the theoretical foundation for why caches work.
Temporal Locality (Locality in Time):
i is read and written every single iteration. Accumulators like sum += A[i] are touched repeatedly. Instruction memory of the loop body is fetched every iteration.Spatial Locality (Locality in Space):
A[0], A[1], A[2]...), sequential instruction fetching (one instruction after another), and accessing fields of a struct or object laid out contiguously in memory.A[0] is requested, the cache also loads A[1] through approximately A[15] (for 4-byte integers). All subsequent accesses to those elements are instant cache hits.Conclusion: Without locality, every memory access would be a cache miss, rendering caches useless. It is precisely because programs exhibit strong temporal and spatial locality that a small, fast cache can intercept 90-99% of all memory accesses, dramatically speeding up execution.
The Memory Hierarchy is organized such that as you move closer to the CPU, memory becomes faster but smaller. Conversely, as you move away from the CPU, memory becomes slower but larger and cheaper.
Arrangement (Slowest/Largest → Fastest/Smallest):
| Level | Technology | Typical Size | Typical Access Time | Cost per GB |
|---|---|---|---|---|
| 7. Secondary Storage | Magnetic Disk (HDD) | 1–20 TB | 5–10 ms | ~$0.02 |
| 6. Flash Storage | NAND Flash (SSD) | 256 GB–4 TB | 25–100 μs | ~$0.10 |
| 5. Main Memory | DRAM | 8–64 GB | 50–100 ns | ~$3 |
| 4. L3 Cache | SRAM | 4–64 MB | ~10 ns | ~$10 |
| 3. L2 Cache | SRAM | 256 KB–1 MB | ~4 ns | ~$10 |
| 2. L1 Cache | SRAM | 32–64 KB | ~1 ns | ~$10 |
| 1. CPU Registers | Flip-Flops | ~1 KB | ~0.25 ns | Highest |
Key Principle: Each level acts as a cache for the level below it. L1 caches data from L2, L2 caches data from L3, L3 caches data from DRAM, and DRAM effectively caches data from the SSD/HDD (via Virtual Memory).
Loops are the single most important source of locality in computer programs. They demonstrate both temporal and spatial locality simultaneously.
Example Code:
int sum = 0;
for (int i = 0; i < 1000; i++) {
sum += A[i];
}
Temporal Locality exhibited:
sum is read and written in every single iteration of the loop (1000 times). After the first access brings sum into the cache, the remaining 999 accesses are all fast cache hits.i (the loop counter) is read and incremented every iteration — also a temporal locality pattern.sum += A[i], the branch, and the increment) are fetched from instruction memory 1000 times. After the first iteration fetches them into the I-Cache, the next 999 iterations are all instruction cache hits.Spatial Locality exhibited:
A[i] is accessed sequentially: A[0], A[1], A[2], ..., A[999]. These elements are stored contiguously in memory.A[0], the cache brings in an entire 64-byte cache block, which also contains A[1] through A[15] (assuming 4-byte integers). This means elements A[1] to A[15] are immediate cache hits without any additional memory requests.Net Result: Due to both types of locality, the cache hit rate for this loop is extremely high (often >95%), meaning the CPU rarely has to wait for slow main memory.
Each type of memory technology serves a specific, irreplaceable role in a computer system. No single technology can fulfill all requirements.
1. SRAM (Static Random-Access Memory):
2. DRAM (Dynamic Random-Access Memory):
3. Flash Memory (NAND) / SSD:
4. Magnetic Disk (HDD):
Locality has a direct and profound impact on cache performance. It is the sole reason caches are effective. Without locality, a cache would have nearly a 0% hit rate and provide no benefit.
Impact on Hit Rate:
Impact on Average Memory Access Time (AMAT):
Impact on Processor Stalls and CPI:
Conclusion: Locality is the single most important factor determining cache performance. Compiler writers and programmers invest significant effort in optimizing data layouts and access patterns (e.g., loop tiling, struct-of-arrays vs. array-of-structs) to maximize locality.
The Inclusion Property (also called Multilevel Inclusion) is a design policy for multi-level cache hierarchies that states: every cache block present in a higher-level (closer to CPU) cache must also be present in the lower-level (farther from CPU) cache.
Formal Definition:
If a cache hierarchy has L1 and L2 caches, the inclusion property requires that:
That is, L1 is a strict subset of L2. Anything in L1 must also be in L2. L2 may contain blocks that are NOT in L1.
Implications and Mechanism:
Drawback:
The total unique cache capacity is reduced. Since L1 data is duplicated in L2, the effective unique storage is just the size of L2, not L1 + L2. This wastes a portion of the L2 space.
The MESI protocol (also known as the Illinois protocol) is a widely used hardware-based cache coherence protocol for multiprocessor systems. It tracks the state of every cache block to ensure that all processors see a consistent view of shared memory. MESI stands for the four possible states of a cache line:
The Four States:
Key Transitions (Examples):
These three policies define the relationship between the contents of different levels in a multi-level cache hierarchy (e.g., L1 and L2). Each has distinct trade-offs.
| Property | Inclusive | Exclusive | Non-Inclusive (NINE) |
|---|---|---|---|
| Rule | L1 ⊆ L2 (L1 is a subset of L2) | L1 ∩ L2 = ∅ (No block is in both) | No constraint. Data may or may not overlap. |
| Unique Capacity | Effective = L2 size (L1 data is duplicated) | Effective = L1 + L2 (maximum utilization) | Between Inclusive and Exclusive |
| On L2 Eviction | Must back-invalidate the block from L1 | Evicted block may be placed into L1 (swap) | No special action needed |
| Coherence | Simplified: Snooping only needs to check L2 | Complex: Must snoop both L1 and L2 | Complex: Must snoop both L1 and L2 |
| Used By | Intel (historically), many server CPUs | AMD Athlon (L1/L2) | Some ARM designs, recent Intel designs |
Key Insight: The choice depends on whether the designer prioritizes coherence simplicity (→ Inclusive) or maximum effective cache capacity (→ Exclusive). Non-Inclusive is a pragmatic middle ground used when neither extreme is desirable.
These are two distinct but related concepts that are essential for correctness in multiprocessor systems. They are often confused but address fundamentally different problems.
| Feature | Cache Coherence | Memory Consistency |
|---|---|---|
| Scope | Deals with a single memory location (address X). | Deals with the ordering of accesses to multiple different memory locations. |
| Problem Addressed | Stale copies in private caches. Multiple processors must read the most recently written value for the same variable. | Instruction reordering by compiler or out-of-order execution hardware making writes visible in an unexpected sequence. |
| Protocol/Model | Enforced by hardware protocol (e.g., MESI, Snooping, Directory protocols). | Enforced by Memory Consistency Models (e.g., Sequential Consistency, TSO, Weak Consistency). |
| Enforcement Level | Invisible to software; handled entirely in the hardware cache hierarchy. | Exposed to software; programmers use memory fences/barriers or synchronization primitives. |
| Core Guarantee | A read to location X eventually returns the most recently written value to location X. | Updates to multiple variables (e.g., Flag and Data) are observed in a legal, consistent order. |
Summary: Coherence guarantees that you get the correct value for a single variable. Consistency guarantees the correct order in which updates to multiple variables become visible across processors. Both are necessary for correct parallel programs.
The inclusion property (L1 ⊆ L2) is a deliberate design choice with significant trade-offs.
Advantages:
Disadvantages:
The write policy determines what happens to main memory when the CPU writes to a cache block. This has a direct and significant impact on how coherence is maintained in multiprocessor systems.
Write-Through Policy:
Write-Back Policy:
Conclusion: Write-back is the dominant policy in modern multiprocessors because the reduced bus traffic far outweighs the added coherence complexity, which is efficiently handled by hardware protocols like MESI.
An inclusive cache hierarchy (where L1 ⊆ L2) has a very significant and beneficial impact on coherence protocol design, particularly for snooping-based protocols.
The Core Benefit — Snoop Filtering:
Performance Impact:
The Tradeoff:
The price paid is the back-invalidation problem: when L2 evicts a block, L1 must also evict it. This can hurt performance if L2 is not sufficiently larger than L1.
Both are hardware mechanisms to ensure that all processors in a shared-memory multiprocessor see a consistent view of memory. They differ fundamentally in how they track which caches hold which blocks.
Snooping-Based Protocols:
Directory-Based Protocols:
Cache organization determines where a memory block can be placed within the cache. This is one of the most critical cache design decisions.
1. Direct-Mapped Cache:
Cache Line Index = Block Address MOD Number of Cache Blocks.| Tag | Index | Block Offset |2. Fully Associative Cache:
| Tag | Block Offset |3. Set-Associative Cache (N-way):
Set Index = Block Address MOD Number of Sets.| Tag | Set Index | Block Offset |Note: Direct-Mapped is a special case of set-associative with 1 way. Fully Associative is a special case with 1 set containing all lines.
When a cache miss occurs in a set-associative or fully associative cache and the set is full, the cache controller must decide which existing block to evict (replace) to make room for the new block. The replacement policy determines this choice.
1. LRU (Least Recently Used):
2. FIFO (First In, First Out):
3. Random Replacement:
4. Optimal (Belady's Algorithm — Theoretical Only):
The choice of replacement policy depends on the hardware constraints and the expected workload behavior.
Cache performance is evaluated by measuring how effectively the cache intercepts memory requests, preventing them from reaching the slower main memory.
1. Hit Rate (H):
2. Miss Rate (M):
3. Average Memory Access Time (AMAT):
AMAT = Hit Time L1 + Miss Rate L1 × (Hit Time L2 + Miss Rate L2 × Miss Penalty L2).This is a straightforward application of the AMAT formula.
Given:
Step 1: Calculate the Miss Rate
Step 2: Apply the AMAT Formula
Conclusion: The Average Memory Access Time is 10 ns.
Interpretation: Even though the cache serves 90% of requests in just 5 ns, the 10% of misses — each costing an additional 50 ns — doubles the average access time to 10 ns. This illustrates why even small improvements in miss rate (e.g., from 10% to 5%) have an outsized impact on AMAT (reducing it from 10 ns to 7.5 ns).
Given:
Step 1: Calculate the Number of Sets
Step 2: Explain the Replacement Policy
The replacement policy dictates which of the 4 blocks within a given set is evicted when a new block needs to be loaded into a set that is already full.
Address Breakdown:
General approach for solving any direct-mapped cache trace problem for an exam:
Step-by-Step Method:
Cache Line = Block Address MOD Number of Cache Lines.Example Trace:
Cache: 4 lines (0-3). Block sequence: 0, 8, 0, 6, 8.
Mapping: Line = Block MOD 4.
| Access | Block | Line (mod 4) | Cache State at Line | Result |
|---|---|---|---|---|
| 1 | 0 | 0 | Empty → Load 0 | MISS |
| 2 | 8 | 0 | Has 0 → Evict, Load 8 | MISS (conflict) |
| 3 | 0 | 0 | Has 8 → Evict, Load 0 | MISS (conflict) |
| 4 | 6 | 2 | Empty → Load 6 | MISS |
| 5 | 8 | 0 | Has 0 → Evict, Load 8 | MISS (conflict) |
Result: 0 Hits, 5 Misses. Blocks 0 and 8 constantly thrash because they both map to Line 0. A 2-way set-associative cache would solve this.
Given: Cache size = 4 blocks. Direct-Mapped. Mapping: Cache Line = Block Number mod 4.
Note: In a Direct-Mapped cache, the "replacement policy" is irrelevant because each block has exactly one possible location. There is no choice about which block to evict — the conflicting block is always overwritten.
| Access # | Block | Line (mod 4) | Cache Lines [0,1,2,3] | Result |
|---|---|---|---|---|
| 1 | 1 | 1 | [-, 1, -, -] | MISS |
| 2 | 2 | 2 | [-, 1, 2, -] | MISS |
| 3 | 3 | 3 | [-, 1, 2, 3] | MISS |
| 4 | 4 | 0 | [4, 1, 2, 3] | MISS |
| 5 | 1 | 1 | [4, 1, 2, 3] | HIT |
| 6 | 2 | 2 | [4, 1, 2, 3] | HIT |
| 7 | 5 | 1 | [4, 5, 2, 3] | MISS (evicts 1) |
| 8 | 1 | 1 | [4, 1, 2, 3] | MISS (evicts 5) |
| 9 | 2 | 2 | [4, 1, 2, 3] | HIT |
| 10 | 3 | 3 | [4, 1, 2, 3] | HIT |
| 11 | 4 | 0 | [4, 1, 2, 3] | HIT |
| 12 | 5 | 1 | [4, 5, 2, 3] | MISS (evicts 1) |
Result: 5 Hits, 7 Misses.
Given: 2 Sets, each with 2 blocks (2-way). Total = 4 blocks. LRU replacement. Mapping: Set = Block MOD 2.
Sets: Set 0 (holds blocks where Block mod 2 = 0) and Set 1 (holds blocks where Block mod 2 = 1).
| Access | Block | Set | Set 0 [Way0, Way1] | Set 1 [Way0, Way1] | Result | LRU in Set |
|---|---|---|---|---|---|---|
| 1 | 0 | 0 | [0, -] | [-, -] | MISS | - |
| 2 | 4 | 0 | [0, 4] | [-, -] | MISS | LRU=0 |
| 3 | 1 | 1 | [0, 4] | [1, -] | MISS | - |
| 4 | 5 | 1 | [0, 4] | [1, 5] | MISS | LRU=1 |
| 5 | 0 | 0 | [0, 4] | [1, 5] | HIT | LRU=4 |
| 6 | 4 | 0 | [0, 4] | [1, 5] | HIT | LRU=0 |
| 7 | 1 | 1 | [0, 4] | [1, 5] | HIT | LRU=5 |
| 8 | 5 | 1 | [0, 4] | [1, 5] | HIT | LRU=1 |
Result: 4 Hits, 4 Misses.
Analysis: The first 4 accesses are compulsory misses (cold starts). The next 4 accesses are all hits because the working set (blocks 0, 4, 1, 5) fits perfectly into the 4-block cache. The 2-way associativity prevents the conflict misses that would destroy performance in a direct-mapped cache with this access pattern.