- Learn
- Computer Science & IT
- Computer Science
- Computer Organization and Architecture
- Memory Hierarchy and Caches
Memory Hierarchy and Caches
IntermediateLesson 5 of 6 in Computer Organization and Architecture Course
What you will learn
- Describe how programs reuse data and code, compare the memory technologies that store it, and explain how fast small levels and slow large levels work together.
- Recognize temporal and spatial locality in programsIdentify the two kinds of locality in code and data accesses and explain why they let a small, fast memory serve most accesses.
- Compare SRAM, DRAM and flash memoryDescribe how SRAM, DRAM and flash store bits and compare their speed, density, cost per bit, volatility and typical place in the hierarchy.
- Describe how the levels of the hierarchy work togetherName the levels from registers to storage, use the vocabulary of hits and misses, and explain how the hierarchy gives the illusion of a large, fast memory.
- Recognize temporal and spatial locality in programs
- Use the tag, index and offset fields of an address to locate a block, trace sequences of accesses, and compare cache organizations from direct-mapped to fully associative.
- Split an address into tag, index and offsetWork out the field sizes of a direct-mapped cache from its capacity and block size, divide an address into its fields and count the storage the cache needs.
- Trace accesses through a direct-mapped cacheFollow a sequence of addresses through a small direct-mapped cache, record each hit or miss and the cache contents, and spot blocks that evict each other.
- Use set-associative and fully associative cachesLocate blocks in n-way set-associative and fully associative caches, choose a victim with a replacement policy, and weigh lower miss rates against hardware cost and hit time.
- Split an address into tag, index and offset
- Describe what happens on a miss, classify misses by cause, relate cache size, block size and associativity to the miss rate, and compare the ways caches handle writes.
- Handle cache misses and classify their causesDescribe the steps of a cache miss, sort misses into compulsory, capacity and conflict misses, and explain how cache size, block size and associativity change each kind.
- Compare write policies for cachesExplain how write-through and write-back caches keep memory up to date, what write buffers and dirty bits do, and how write-allocate and no-write-allocate handle write misses.
- Handle cache misses and classify their causes
- Compute hit rates, average memory access time and memory-stall cycles, include them in CPI and execution time, and analyze systems with several levels of cache.
- Compute hit rate and average memory access timeCalculate hit and miss rates and the average memory access time of a cache, including mixes of instruction and data accesses, and use it to compare designs.
- Include memory stalls in CPI and execution timeAdd memory-stall cycles to the CPU performance equation, find how much a cache costs a program, and explain why faster processors suffer more from slow memory.
- Analyze multilevel cachesExplain why processors use several cache levels, distinguish local and global miss rates, and compute average memory access time and CPI for two- and three-level hierarchies.
- Compute hit rate and average memory access time
- Describe how virtual addresses are translated to physical addresses with a page table, why a page fault is a miss handled by the operating system, and how the TLB makes translation fast.
- Translate a virtual address with a page tableExplain what virtual memory provides, split a virtual address into page number and offset, translate it through a page table entry, and describe what happens on a page fault.
- Speed up translation with a TLBExplain how the translation lookaside buffer caches translations, follow an access through the TLB, page table and cache, and see how caches and translation overlap.
- Translate a virtual address with a page table
- Organize loops and data structures so that programs use the memory hierarchy well, and apply blocking and prefetching to reuse data while it is cached.
- Arrange loops and data for localityOrder loops to match how arrays are stored, avoid harmful strides, and choose data layouts that bring only useful data into the cache.
- Block computations and use prefetchingRestructure loops into blocks (tiles) that stay in the cache while they are reused, choose a block size, and explain how hardware and software prefetching hide memory latency.
- Arrange loops and data for locality
Memory Hierarchy and Caches study guide
1Explain why computers use a memory hierarchy
Programs repeatedly use a small part of their code and data. That reuse explains why a small cache can serve most accesses even when the whole program is much larger. Follow the difference between reuse in time and nearby addresses, compare the cells behind SRAM, DRAM, and flash, and connect those technologies to hits, misses, and transfers through the hierarchy. The same access pattern will later determine whether a cache design or a loop transformation helps.
1.1 How programs reuse nearby data
A cache works because the next memory access is often related to a recent one. During a short interval, most programs use only a small part of their address space. This pattern is locality. A cache keeps that active part close to the processor, where it can serve accesses quickly.
Reuse in time and space
Temporal locality means reusing an item soon after accessing it. A loop repeatedly fetches its body instructions. A running total is read and updated many times. Keeping those items available avoids fetching them again from a slower level.
Spatial locality means accessing items at nearby addresses. An array scan reads adjacent elements, and straight-line code fetches successive instructions. A cache exploits this by fetching an entire block, also called a cache line, on a miss. Nearby bytes arrive before the program asks for them.
These patterns can occur together. A loop's instructions are adjacent and run repeatedly, so the instruction stream has both spatial and temporal locality. An array element read exactly once has no temporal reuse, even though the surrounding array scan has spatial locality.
Count blocks in an array scan
Consider this C loop with 4-byte integers and 64-byte cache blocks:
for (int i = 0; i < 1000; i++) {
sum += a[i];
}
A block holds integers. The array occupies bytes. If its first element is block aligned, the scan touches blocks: 62 full blocks and one partial block.
In a cold cache without prefetching or interference, the first access to each block misses. The remaining elements in that block hit. Thus the array causes 63 misses in 1000 accesses, or about 6.3%. Counting one miss per element would overlook all the useful neighboring data fetched with each miss.
The source variables sum and i are reused frequently. A compiler usually keeps them in registers, however, so their source-level reuse need not produce data-cache accesses. Analyze the memory accesses executed by the compiled program when estimating cache traffic.
The working set must fit and coexist
The working set is the collection of blocks used during a chosen time window. If they fit in the cache and the placement rules allow them to coexist, repeated accesses mostly hit after the initial loads. The time window matters: a whole program can be huge while one active loop uses only a few blocks.
Capacity alone is insufficient. Two busy blocks can map to one direct-mapped entry and evict each other while other entries remain empty. A working set can therefore fit by byte count yet fail to stay cached.
Scattered linked-list nodes and random probes of a large hash table often have poor spatial locality. A column walk through a row-major array also skips over many nearby elements. These patterns bring in bytes that may go unused before eviction. Hardware exploits the locality supplied by the access pattern; changing the program's layout or traversal can make more of each fetched block useful.
Key Takeaways
- Temporal locality reuses an item; spatial locality accesses nearby addresses.
- Fetching a whole block makes later accesses to nearby bytes hit.
- A working set must fit in capacity and coexist under the cache placement rules.
- Source variables kept in registers do not generate data-cache accesses.
1.2 Memory cells, transfers, and trade-offs
Memory technologies trade speed against density, cost, and persistence. The processor needs quick access to a small amount of data and affordable space for much more. SRAM, DRAM, and flash meet different parts of that need.
Compare the cells
| Technology | How a bit is stored | Refresh and power | Main role |
|---|---|---|---|
| SRAM | A stable circuit, typically six transistors | No refresh; loses data without power | On-chip caches |
| DRAM | Charge on a capacitor, accessed through a transistor | Periodic refresh; loses data without power | Main memory |
| NAND flash | A nonvolatile cell whose state is electrically programmed | Retains data without power; limited write endurance | Storage |
An SRAM cell is fast but occupies substantial area, making SRAM relatively expensive per bit. DRAM cells are smaller, so DRAM provides more capacity at a lower cost per bit. Their charge leaks away. Refresh reads and restores rows within a fixed window; normal-temperature DDR4 uses a 64 ms window. “Static” in SRAM means no refresh, not persistence after power loss.
Why DRAM access time varies
DRAM is organized into banks, with rows and columns in each bank. Activating a row copies it into a row buffer. Reads and writes then select columns from that open row. To open a different row in the same bank, the bank must first be precharged. An access to an already open row avoids that row-switching work.
Consecutive columns can be transferred in a burst, which suits fetching a cache block. Distributing requests across banks and channels lets transfers overlap. DDR memory transfers on both clock edges. These features increase the rate of data delivery without eliminating the wait for the first data.
Separate latency from bandwidth
Latency is the delay until the first data arrives. Bandwidth is the amount transferred per unit time. A high-bandwidth interface can still have a long initial delay.
For example, a DDR5-4800 channel with an aggregate 64-bit data path carries 8 bytes per transfer. Its peak rate is bytes/s, or 38.4 GB/s. Sustained application bandwidth can be lower because commands, row changes, and other work consume time.
If a request waits 60 ns and then receives a 64-byte block at 16 GB/s, the transfer rate is 16 bytes/ns. Transfer takes ns, giving about 64 ns altogether. Improving only bandwidth reduces the 4 ns part, not the initial 60 ns.
Flash keeps data but handles writes differently
NAND flash reads and programs pages of several KiB. Reusing a programmed page requires erasing its larger erase block, which contains many pages. Page reads typically take tens of microseconds, programming hundreds of microseconds to a few milliseconds, and erasing milliseconds.
Program/erase cycles wear cells out. Dense multi-bit flash often supports a few thousand cycles, while single-bit cells can support around 100,000. Controllers use wear leveling to spread writes across blocks.
For scale, SRAM access is roughly 1 ns, DRAM roughly 50–100 ns, NAND reads roughly 25–100 µs, and disk access roughly 5–10 ms. Actual devices vary. The hierarchy combines these technologies because a single one cannot provide their speed, capacity, and price advantages together.
Key Takeaways
- SRAM and DRAM are volatile; flash retains data without power.
- DRAM refresh restores leaking charge, while row buffers and bursts improve access efficiency.
- Latency measures initial waiting time; bandwidth measures transfer rate.
- Flash programs pages and erases larger blocks.
- Wear leveling spreads program/erase wear across flash blocks.
1.3 Follow an access through the hierarchy
The memory hierarchy places small, fast storage near the processor and progressively larger storage farther away. Locality lets the small levels serve a large fraction of requests, while the lower levels supply capacity.
Levels and transfer units
A typical path is registers, L1, L2, L3, main memory, and storage. L1 commonly has separate instruction and data caches of around 32–64 KiB each per core. L2 is often hundreds of KiB to a few MiB per core, while L3 is often shared and holds several to tens of MiB. Main memory holds many GiB, and storage holds hundreds of GB or more. Designs differ in size and sharing.
On a processor near 3 GHz, representative load latencies are about 4–5 cycles for L1, 12–15 for L2, 30–50 for L3, and 200–300 for DRAM. An L1 may accept a new request each cycle even when one request needs several cycles to complete: throughput and latency describe different properties.
Data travels through caches in blocks, commonly 64 bytes. Virtual memory uses pages, commonly 4 KiB, when moving page contents between memory and storage. A cache line and a page serve similar grouping purposes at different scales; they are not the same transfer unit.
Hits, misses, and timing
A hit means a level contains the requested data. A miss means it must obtain the data from below. Both words refer to the level being checked: an L1 miss can still be an L2 hit.
The hit rate is hits divided by accesses, and the miss rate is one minus the hit rate. Hit time includes checking the level and deciding whether the request hits. The miss penalty is the additional time needed on a miss to obtain and deliver the block.
Suppose a simplified cache has a 1-cycle hit time, a 97% hit rate, and a 100-cycle extra miss penalty. Every access pays 1 cycle, while 3% pay another 100:
A miss takes 101 cycles in this example. Using 100 as the complete miss time would charge the hit lookup inconsistently. Even a high hit rate leaves expensive misses visible in the average.
Who manages each level?
The compiler assigns suitable values to registers. Cache hardware moves blocks automatically as loads, stores, and instruction fetches run. Programs name addresses; they do not select cache entries. The operating system manages virtual-memory mappings with hardware support and handles pages that must be brought into main memory.
Splitting L1 instructions from data allows a pipeline to fetch an instruction and access data together without competing for one cache port. Lower caches are usually unified, storing both instruction and data blocks.
Some hierarchies are inclusive: a block present above also has a copy below. Others are exclusive or non-inclusive, so a copy in every lower cache is not guaranteed. Draw a hierarchy as a search and transfer path, not a promise that all levels contain identical subsets.
Making L1 larger can reduce misses but increase access delay and energy. Adding larger lower caches allows the design to keep L1 fast while rescuing many of its misses before DRAM. Evaluate that trade-off with access time, not capacity alone.
Key Takeaways
- A hit or miss is relative to the level being checked.
- Hit time is paid on every lookup; miss penalty is additional time on misses.
- Caches transfer blocks, while virtual memory uses pages.
- Separate L1 instruction and data caches support simultaneous pipeline accesses.
- Cache inclusion is a design choice.
- Larger capacity must be weighed against hit time and energy.
2Find data in direct-mapped and set-associative caches
A memory address must tell a cache where to look and which bytes to return. Divide addresses into fields, track how requests replace blocks, and then give each block more placement choices through sets and ways. Small traces make the hardware rules visible: a different byte can hit in a loaded block, while a repeatedly used block can miss after a conflict. These lookup rules also determine how many tags and control bits the cache must store.
2.1 Find tag, index, and offset
A byte address identifies one byte in memory. A cache fetches a whole block, so lookup first identifies that block and then selects the requested bytes within it. In a direct-mapped cache, each block has exactly one possible entry.
Divide the address by purpose
For a block size of bytes, the low address bits form the offset. Dividing the byte address by the block size and discarding the remainder gives the block address. The remainder is the offset.
If the cache has entries, the entry index is
With a power-of-two entry count, the index is the group of address bits immediately above the offset. The remaining high bits form the tag, which tells the cache which of the many blocks sharing an index is present.
The field order from high bits to low bits is tag | index | offset. For an address width of bits:
Use the number of entries for the index calculation. Taking the logarithm of capacity in bytes would count the offset bits a second time.
Work a 16 KiB example
A 16 KiB direct-mapped cache with 64-byte blocks has entries. The offset takes 6 bits, the index 8 bits, and the tag bits for 32-bit addresses.
For byte address 0x1234ABCD, the low 6 bits give offset 13, or 0x0D. Removing those bits gives block address 0x48D2AF. Its low 8 bits are 0xAF, so the index is 175. The remaining bits give tag 0x48D2.
The byte address can be reconstructed from these fields: concatenate the tag, the 8-bit index, and the 6-bit offset. Field widths matter because a hexadecimal digit represents 4 bits; the boundaries need not fall between hex digits.
A matching tag needs a valid entry
Each entry stores data, a tag, and a valid bit. The index selects the entry. A hit requires both a set valid bit and equality between its stored tag and the requested tag. At startup, an entry can contain arbitrary bits; the valid bit prevents those bits from being mistaken for a loaded block.
Once the block is present, accesses to other bytes in that block hit too. A hit does not require the identical byte address used to fetch the block.
Count metadata separately
Quoted cache capacity normally counts data only. Here each entry contains 512 data bits, 18 tag bits, and 1 valid bit, or 531 bits. Total storage is
The data alone uses 131072 bits. Tags and validity add 4864 bits, about 3.7% of data storage. A write-back design also needs dirty bits; more complex designs need further control state.
The index uses low block-address bits so successive blocks spread across successive entries. A wider address leaves offset and index widths unchanged when capacity and block size stay fixed; the extra bits extend the tag.
Key Takeaways
- Compute entry count from data capacity divided by block size.
- The low address bits select the byte offset; the next bits select the entry.
- A hit requires a valid entry and matching tag.
- Advertised data capacity excludes tags and control bits.
2.2 Trace a direct-mapped cache
A cache trace records how each access changes the stored blocks. Keep a separate state for each entry, and update that state immediately after every miss. The next request uses the updated cache, not the cache as it looked at the beginning.
Set up the trace
Take a 64-byte direct-mapped cache with four 16-byte entries. It starts empty. For each byte address, divide by 16 to find the block, then compute block modulo 4 for the index. The tag is the block number divided by 4, with its fractional part discarded. There are 4 offset bits and 2 index bits.
On a read, inspect the selected entry. If it is valid and the tag matches, record a hit. Otherwise record a miss, replace that entry's block and tag, and set its valid bit. No replacement choice is available in a direct-mapped cache.
Follow all eight accesses
| Byte address | Block | Index | Tag | Result | Block left in selected entry |
|---|---|---|---|---|---|
0x00 | 0 | 0 | 0 | Miss | 0 |
0x04 | 0 | 0 | 0 | Hit | 0 |
0x40 | 4 | 0 | 1 | Miss | 4 |
0x00 | 0 | 0 | 0 | Miss | 0 |
0x14 | 1 | 1 | 0 | Miss | 1 |
0x44 | 4 | 0 | 1 | Miss | 4 |
0x08 | 0 | 0 | 0 | Miss | 0 |
0x84 | 8 | 0 | 2 | Miss | 8 |
The first access fills entry 0 with block 0. The next address, 0x04, is still inside that 16-byte block, so it hits despite naming a different byte. 0x40 belongs to block 4. It has the same index as block 0 but a different tag, so it replaces block 0.
The second 0x00 therefore misses. Earlier use alone cannot guarantee a hit: the block must still be present. The request to 0x14 loads block 1 into entry 1, leaving entry 0 unchanged.
Next, 0x44 loads block 4 into entry 0 again. 0x08 needs block 0 and evicts block 4. Finally, 0x84 loads block 8 into that same entry. At the end, entry 0 holds block 8 and entry 1 holds block 1; entries 2 and 3 remain invalid.
Interpret the behavior
There is one hit and seven misses, so the hit rate is . Blocks 0, 4, and 8 compete for entry 0. The cache has four entries, yet this access pattern uses only two of them. The repeated evictions are caused by mapping conflicts, not a shortage of total storage for the four distinct blocks.
A block fill makes all of that block's bytes available. In a sequential scan, one miss can therefore serve many following elements. Here the conflicting accesses repeatedly remove that benefit before the next nearby byte is requested.
For reliable tracing, label byte addresses and block numbers explicitly. Applying modulo 4 directly to the byte address skips the division by block size and sends requests to the wrong entries. Record the replacement even when the new block has been loaded before: every miss installs the requested block and its tag in the selected entry.
Key Takeaways
- Update cache contents after every miss.
- Different byte addresses in one resident block hit.
- A previously accessed block can miss after eviction.
- Mapping conflicts can cause misses while other entries remain empty.
- The example has one hit in eight accesses, a 12.5% hit rate.
2.3 Give blocks more placement choices
A set-associative cache gives a block several possible entries without searching the entire cache. The index selects a set, and the block can occupy any way in that set. This reduces conflicts between blocks that share an index.
Compute sets and fields
For data capacity , block size , and associativity :
The set index is block address modulo the number of sets. The offset still depends only on block size. The tag contains the remaining high bits.
A 32 KiB, 8-way cache with 64-byte blocks has 512 blocks and 64 sets. With 32-bit addresses, its offset, index, and tag widths are 6, 6, and 20 bits. Address 0x1234ABCD has offset 13, set 47, and tag 0x1234A.
At fixed capacity and block size, doubling associativity halves the number of sets. One index bit becomes a tag bit; no data capacity is added.
| Organization | Allowed placement | Index |
|---|---|---|
| Direct-mapped | One entry | Selects that entry |
| n-way | Any of n ways in one set | Selects that set |
| Fully associative | Any entry in the cache | No index field |
Lookup compares the tag with all valid tags in the chosen set in parallel. A matching way supplies the data through a selector. More ways require more comparisons and selection hardware, which can increase hit time and energy.
Replace a block only when the set is full
Use an invalid way first. When every way is occupied, LRU, or least recently used, evicts the block whose most recent access is oldest. Update recency on hits as well as fills. A 2-way set needs only one bit to track its LRU way; larger sets often use pseudo-LRU approximations.
FIFO evicts the block loaded earliest, even if it was recently accessed. Random replacement chooses a victim without maintaining full recency information. It is simple and can perform close to LRU in large caches.
Revisit the small trace with two ways
The 64-byte cache with 16-byte blocks now has two sets of two ways. Blocks 0, 4, and 8 map to set 0, while block 1 maps to set 1. For 0x00, 0x04, 0x40, 0x00, 0x14, 0x44, 0x08, 0x84, the results are miss, hit, miss, hit, miss, hit, hit, miss.
Blocks 0 and 4 can coexist, so their repeated accesses hit. Just before the last access, block 0 was used more recently than block 4. Loading block 8 evicts block 4 under LRU. Four of eight accesses hit, compared with one in the direct-mapped version.
Associativity cannot remove compulsory misses or make a working set larger than capacity fit. It also cannot prevent conflicts when more than n busy blocks compete for one n-way set. A repeating cycle of n+1 such blocks can make LRU miss every time. Padding arrays can change their set mappings; choosing more ways is only one possible response to a conflict problem.
Key Takeaways
- Set count equals data capacity divided by block size and ways.
- More associativity changes placement flexibility, not data capacity.
- LRU tracks accesses; FIFO tracks insertion order.
- Fill invalid ways before replacing valid blocks.
- Fully associative caches have no index field but still have cold and capacity misses.
- More ways can reduce conflict misses at a hardware and timing cost.
3Explain cache misses and write policies
A miss can come from first use, limited capacity, or blocks competing for the same locations. Identifying its cause helps explain which design changes can reduce it. Stores add a second problem: the hierarchy must decide when changed data reaches the next level and what happens if the block is absent. Follow read-miss service, write policies, buffers, and dirty evictions to connect cache state with the traffic and delays it produces.
3.1 Explain what caused a miss
A cache miss is an event with both a mechanism and a cause. The mechanism describes how the request is served. The cause explains why the needed block was absent and which design change might help.
Handle a read miss
In a simple in-order pipeline, the cache detects an invalid entry or a tag mismatch, and the processor stalls. The cache requests the block from the next level. If the chosen victim is dirty, its changed data must be preserved by writing it back. The arriving block is installed with its tag and valid bit, and the waiting access completes. An instruction-cache miss similarly waits for the instruction's block and then fetches the instruction again.
Critical word first requests the needed word first in the returning block. Early restart lets execution resume as soon as that word arrives. A nonblocking cache can serve other hits and track outstanding misses while an out-of-order processor does independent work. These mechanisms reduce waiting; they do not make the original data dependency disappear.
Use the three Cs
| Miss class | Why the block is absent | Diagnostic test |
|---|---|---|
| Compulsory | This is its first access | It would miss even with unlimited capacity |
| Capacity | The active blocks exceed available space | A same-size fully associative LRU cache also misses |
| Conflict | Placement restrictions evicted it | A same-size fully associative LRU cache hits |
Apply the first-access test first. A block's first access is compulsory even if its destination entry is already occupied. For later misses, compare the actual cache with a fully associative LRU cache of equal data capacity and block size, both receiving the same access history.
In the earlier four-entry trace, blocks 0, 4, 1, and 8 each cause one compulsory miss. The direct-mapped cache also misses on the repeated accesses to blocks 0 and 4. A four-entry fully associative cache can retain all four distinct blocks, so those three repeat misses are conflicts. There are no capacity misses.
Choose a change that addresses the cause
Increasing capacity can retain a larger working set. Increasing associativity can let conflicting blocks coexist. Increasing block size can exploit spatial locality by bringing in more useful neighbors with each fill.
Block size has competing effects. At fixed data capacity, larger blocks mean fewer resident blocks. Unused bytes consume cache space, unrelated useful blocks can be displaced, and each transfer can take longer. Miss rate often falls initially as block size grows, then rises when these costs outweigh useful spatial locality.
A larger cache can also have a longer lookup, and additional ways require more comparison hardware. Judge changes through average access time, including hit time and miss penalty, instead of assuming that a lower miss rate guarantees a faster design.
In multicore systems, invalidation after another core writes can cause coherence misses. Prefetching can bring a first-use block in before its demand access, hiding a demand miss that additional capacity alone cannot avoid.
Key Takeaways
- Classify first accesses as compulsory before checking other causes.
- Use a same-size fully associative LRU cache to distinguish capacity from conflict misses.
- Larger blocks trade useful spatial locality against fewer resident blocks and longer transfers.
- Early restart, critical word first, and nonblocking caches reduce waiting in different ways.
- Compare full access time when judging a miss-rate improvement.
3.2 Decide when stores reach the next level
A store changes a value, so the hierarchy needs a rule for passing that change downward. Two separate choices are involved: what to do when a store hits, and what to do when it misses.
Write-through and write-back
| Policy | Action on a write hit | Effect on the next level |
|---|---|---|
| Write-through | Update the cache and send the store downward | Every store generates a lower-level update |
| Write-back | Update the cache and mark its block dirty | A dirty block is sent down when evicted |
A dirty bit records that a write-back block contains changes not yet written to the next level. A clean victim needs no write-back. A dirty victim must have its changed data preserved before its entry can be reused. The processor's loads obtain the new value from the cache even while the lower copy is older.
For 100 stores to one cached 4-byte variable, unmerged write-through sends 100 writes, or 400 bytes of data payload. Write-back can combine those changes into one 64-byte block write on eviction. This comparison counts update payload, excluding the initial fill and protocol overhead.
The benefit depends on reuse. Repeated writes to one block give write-back a chance to combine updates; writes scattered across many blocks may lead to many dirty evictions. Lower caches commonly use write-back to limit traffic toward DRAM. L1 data caches can use either policy.
A write buffer hides waiting, not traffic
A write buffer queues pending lower-level writes. Under write-through, the processor can proceed once a store has entered the buffer instead of waiting for the lower memory to finish. The lower level catches up as buffered stores drain; it can temporarily lag behind the cached value.
The buffer has finite capacity. If stores arrive faster than the lower level accepts them for long enough, it fills and the processor stalls. A buffer changes when the processor waits, not the sustainable bandwidth of the destination.
Without buffering or overlap, if 10% of instructions store and every store adds 100 wait cycles, a base CPI of 1 becomes . Buffering can hide much of this delay when the destination keeps up on average.
Treat a write miss separately
Write-allocate fetches the missing block into the cache and then applies the store. It pairs naturally with write-back because later accesses and writes can reuse that block. No-write-allocate, also called write-around, sends the store downward without filling this cache. It pairs naturally with write-through and can avoid displacing useful blocks during a one-time output stream.
These are independent policy choices. Knowing that a cache is write-through does not by itself tell you whether a write miss allocates a line; a trace must specify both policies.
A write-back miss that selects a dirty victim involves outgoing data as well as the incoming fill, raising the penalty unless buffers or overlap hide part of the work. Other cores and I/O devices also need a consistent view when lower memory is stale. Coherence and system mechanisms coordinate that visibility; a dirty bit alone only records pending changes.
Key Takeaways
- Write-through sends each store downward; write-back delays changes until dirty-block write-back.
- A dirty bit distinguishes modified blocks from clean ones.
- Write buffers hide latency until they fill; they do not create bandwidth.
- Write-allocate and no-write-allocate specify write-miss behavior independently of the hit policy.
- A dirty eviction adds outgoing traffic to the miss path.
- Buffered write-through can leave the lower level temporarily behind.
4Calculate cache performance
A cache design is useful only if its hits and misses lead to better execution time. Combine lookup time, miss frequency, and extra miss delay, then connect access costs to stalls per instruction. Separate instruction and data traffic, keep cycles consistent with clock time, and nest lower-cache costs using the fraction of requests that reaches each level. These calculations show why a lower miss rate or faster clock can give a smaller benefit than expected.
4.1 Calculate average memory access time
A high hit rate is useful, but it is not a complete performance measure. A small number of expensive misses can dominate the average, and a design that avoids more misses can still lose if its lookup becomes too slow.
Start with rates and timing definitions
The two fractions sum to one. Convert percentages to fractions before multiplying: 5% is 0.05.
Average memory access time, or AMAT, is
Every request checks the cache, including requests that miss. The penalty is the extra delay after that lookup. Equivalently, weight hit time by the hit fraction and total miss time by the miss fraction; expanding gives the same formula.
With a 1-cycle hit time, 5% misses, and a 100-cycle additional penalty, AMAT is cycles. At 2 GHz, each cycle lasts 0.5 ns, so this is 3 ns. Do all arithmetic in cycles or all in time, then convert the final result if needed.
Compare complete designs
Cache A has a 1.0 ns lookup and 5% misses. Cache B has a 1.2 ns lookup and 3.5% misses. With a 50 ns penalty:
B wins because avoiding expensive misses more than repays its slower lookup. If the penalty falls to 10 ns, A takes 1.5 ns and B takes 1.55 ns. Now A wins. A miss-rate improvement has value in proportion to the penalty it avoids.
Weight instruction and data accesses correctly
Suppose each instruction produces one instruction fetch and 0.3 data accesses on average. The instruction miss rate is 2%, and the data miss rate is 4%. In 100 instructions, there are 100 fetches and 30 data accesses. Expected misses are out of 130 accesses.
The combined miss fraction is therefore With equal 1-cycle hit times and 100-cycle penalties, AMAT is about 3.46 cycles per memory access. Averaging 2% and 4% directly would wrongly give the two access types equal weight.
Estimate a transfer penalty
A block request can include initial latency followed by transfer time. With 60 ns latency, a 64-byte line, and 16 GB/s bandwidth, transfer takes 4 ns, making the additional penalty about 64 ns. At 3 GHz, there are 3 cycles/ns, so that is 192 cycles.
Check what a problem's timing includes. If it gives a complete miss access time, subtract the hit lookup before treating that number as an additional miss penalty. Charging the lookup twice overstates AMAT.
Key Takeaways
- AMAT adds the hit lookup to the expected extra miss cost.
- Use decimal miss fractions and one consistent timing unit.
- Weight instruction and data rates by their access counts.
- A lower miss rate can lose to a sufficiently slower hit time.
4.2 Turn misses into execution time
AMAT measures time per memory access. CPI measures cycles per executed instruction. To connect them, count how many instruction and data requests each instruction produces and how many stall cycles those requests add.
Add the stall terms
For a simple in-order processor whose cache hits are included in the base CPI, a nonoverlapped miss adds its extra penalty. With instruction miss rate , data accesses per instruction , data miss rate , and penalty in cycles:
Every instruction has one instruction-fetch request in this model. Only loads and stores make data requests, so multiply their miss rate by their frequency. If their penalties differ, use a separate penalty in each term.
Work from requests to stalls
Let base CPI be 1.0, instruction miss rate 2%, load/store frequency 30%, data miss rate 4%, and miss penalty 100 cycles. Instruction stalls are cycles per instruction. Data stalls are . Total CPI is 4.2.
With a perfect cache, CPI would return to 1.0. At the same clock and instruction count, that would be a 4.2-fold speedup. The data miss rate is twice the instruction miss rate, yet instruction misses cost more total time because every instruction is fetched and only 30% access data.
Do not insert AMAT directly as CPI. AMAT is per access, and it includes the hit service time. The CPI calculation here adds only stalls beyond the base execution already counted.
A faster clock makes each memory wait cost more cycles
DRAM latency in nanoseconds does not shrink when the processor clock increases. Doubling the clock converts the same 100-cycle memory wait into 200 cycles at the new clock. The example's CPI becomes
Each new cycle is half as long, so relative execution time changes from 4.2 old cycles per instruction to the equivalent of 3.7 old cycles. Speedup is , far below two.
Improvements shift the bottleneck
If the base CPI drops from 1.0 to 0.5 while memory stalls remain 3.2, total CPI becomes 3.7. Stalls now consume of cycles. Improving the core makes the unchanged memory delay a larger share of runtime, an example of Amdahl's law.
The simple model counts all miss delays as stalls. Out-of-order execution and nonblocking caches can overlap misses with useful work or other misses. Hardware counters and runtime measurements are needed to assess that overlap on a real machine. When comparing designs with this model, keep the same instruction stream and state which delays are already included in the base CPI.
Key Takeaways
- Count instruction misses for every instruction and data misses only for data accesses.
- Add extra miss stalls to a base CPI that already includes hits.
- Convert memory time to cycles again when the clock rate changes.
- Compare runtime through CPI times cycle time, not CPI alone.
- Overlap can make actual stalls smaller than the simple sum of miss penalties.
4.3 Nest the costs of several cache levels
A lower cache reduces the penalty paid when L1 misses. It has its own lookup time and miss rate, so the hierarchy's expected cost must follow the fraction of requests that reaches each level.
Keep the denominator with the rate
A level's local miss rate is its misses divided by requests to that level. Its global miss rate is its misses divided by all processor memory requests.
If L1 misses 4% of the time and L2 misses on 25% of those requests, only , or 1% of original requests, reach memory. A 25% local L2 miss rate says nothing by itself about the fraction of all requests reaching memory: L1 filtered the stream first.
For two sequentially checked levels:
Here and are lookup times, and are local miss fractions, and is the additional memory penalty. Only L1 misses pay the L2 lookup. Only misses in both levels pay the memory penalty.
Evaluate from the inside outward
Use L1 hit time 1 cycle, L1 miss rate 4%, L2 hit time 12 cycles, local L2 miss rate 25%, and memory penalty 200 cycles. A request that reaches L2 takes an average of extra cycles. Thus
Without L2, AMAT would be cycles. The L2 lookup adds work to each L1 miss but prevents most of those requests from paying the much larger memory delay.
Do not substitute the 1% global L2 miss rate for inside the parentheses. That would multiply by the L1 miss fraction twice. An equivalent expanded form uses the global rate directly:
Add L3 using the same logic
With L3 hit time 40 cycles and local miss rate 40%, the L3 service term is cycles. The L2 term becomes cycles. Overall AMAT is cycles.
The full expression is L3 is charged only to requests that miss both upper levels. A level with a very slow lookup or very few hits can add more delay than it saves.
Use rates per instruction for CPI
Suppose base CPI is 1, L1 produces 0.032 misses per instruction, and memory adds 100 cycles. With no L2, CPI is . Add a 10-cycle L2 whose local miss rate is 25%:
At the same clock, speedup is . The 0.032 figure is already misses per instruction, so another access-frequency multiplier would count that frequency twice.
Key Takeaways
- Local and global miss rates have different denominators.
- Multiply local miss fractions to find the fraction reaching a lower level.
- Evaluate nested service times from the lowest level upward.
- Charge lower-level lookup time only to requests that reach that level.
- Use misses per instruction directly when calculating stall CPI.
- Adding a cache helps only when avoided delay exceeds its added lookup work.
5Explain how virtual memory and TLBs fit into the hierarchy
Programs issue virtual addresses, while caches ultimately identify physical data. Page tables supply the mapping and access rights, and a TLB keeps recently used translations close to the processor. Work through an address translation, distinguish a missing translation from a page fault, and see how cache indexing can overlap translation. The same hierarchy ideas apply here, but translation entries, data blocks, and pages have different jobs.
5.1 Translate pages and check permissions
Virtual memory separates the addresses a program uses from the locations holding its data in main memory. Each process gets its own virtual address space. Hardware translates addresses using operating-system mappings and checks whether each requested access is permitted.
Replace the page number, preserve the offset
A page is a fixed-size region of virtual addresses. A page frame is a page-sized slot in physical memory. With 4 KiB pages, each page contains 4096 bytes, so the page offset needs 12 bits. The remaining high virtual-address bits form the virtual page number, or VPN.
A page table entry, or PTE, maps a VPN to a physical page number, or PPN. Translation replaces the page number but preserves the offset: the same byte position is selected inside the physical frame.
For virtual address 0x00403A7C, the low 12 bits give offset 0xA7C, and the VPN is 0x00403. If that VPN maps to PPN 0x02F1C, the physical address is 0x02F1CA7C. Appending a 12-bit offset is equivalent to multiplying the PPN by 4096 and adding the offset; adding the unshifted PPN would give the wrong address.
A mapping includes permissions
A PTE records validity, a physical page number, and permissions such as read, write, execute, and user access. Accessed and dirty bits record use and modification. A privileged processor register identifies the page table; RISC-V uses satp. User programs cannot freely rewrite these mappings.
Separate page tables let the same virtual address refer to different physical data in different processes. They also allow selected sharing: two processes can map virtual pages to the same physical frame, for example to share read-only library code. Isolation and sharing are both consequences of controlled mappings.
A page fault needs operating-system attention
A page fault is an exception raised when translation or its permission checks cannot complete normally. A store to a read-only mapping can fault even if the page is already in memory.
When a needed page is absent from main memory, the operating system obtains a physical frame, reads the page from storage, updates the mapping, and restarts the instruction. A modified victim page may first need a write-back. Some faults are resolved without storage, such as setting up a mapping to an existing page or handling copy-on-write. An access the system cannot permit can instead end in a process error.
Storage-backed faults are expensive. At 3 GHz, a 50 µs delay costs 150000 cycles, and 1 ms costs 3000000. Large pages spread transfer costs across many bytes. A virtual page can occupy any suitable frame, and dirty pages use write-back because forwarding every store to storage would be too slow.
Page tables also consume memory
A flat table for 32-bit virtual addresses and 4 KiB pages needs entries. At 4 bytes per entry, that is 4 MiB per process. Real designs use multi-level tables to avoid allocating one huge flat table for sparse address spaces; RISC-V Sv39 uses three levels.
Virtual memory includes address translation, protection, and sharing even when every used page fits in DRAM. Storage-backed paging is one use of that machinery, not its whole purpose.
Key Takeaways
- Translation changes the page number and preserves the page offset.
- PTE permissions control reads, writes, execution, and user access.
- A page fault can mean a missing page or a permission problem.
- Some page faults are resolved without reading storage.
- Page tables support process isolation and deliberate sharing.
- A flat table has one entry per virtual page, so its storage cost can be large.
5.2 Cache translations with a TLB
Address translation can require several page-table reads before a data access proceeds. Page-table entries can hit in ordinary caches, but those reads still add work. The translation lookaside buffer, or TLB, caches recently used translations so most accesses can avoid a page-table walk.
Follow an allowed access
The virtual page number is looked up in the TLB. A matching entry supplies the physical page number and permission information. After permission checks, the physical address identifies the data in the cache hierarchy.
On a TLB miss, a page-table walk obtains the translation. If the mapping is valid and permits the request, the translation is installed in the TLB and the access continues. RISC-V and x86-64 normally use hardware walkers; some architectures use software handlers. If the mapping cannot serve the request, the processor raises a page fault for the operating system.
A TLB miss can therefore accompany either a data-cache hit or a data-cache miss. It says that the translation was absent from the TLB, not that the page was absent from DRAM. Conversely, a TLB hit can accompany a cache miss, or a permission fault for a prohibited access. Translation and data residency answer different questions.
Count the memory covered by translations
TLB reach is entries multiplied by page size. A 64-entry TLB with 4 KiB pages covers 256 KiB at once. With 2 MiB pages, 64 entries cover 128 MiB. Accessing many different pages can exhaust translation capacity even when only a few bytes of each page are used.
First-level TLBs often contain tens of entries; lower TLB levels can contain hundreds or thousands. Their entries include page-number tags, physical mappings, permissions, and often address-space identifiers. Locality within pages and reuse across nearby accesses keep translation hit rates high.
For example, if 1% of accesses require a 30-cycle walk and TLB-hit time is otherwise hidden, walks add cycles per access on average. This example assumes the walks complete normally and excludes page-fault service.
Overlap indexing with translation
A physically indexed, physically tagged cache waits for a physical address before selecting its set. A virtually indexed, physically tagged cache, or VIPT cache, starts reading a set while the TLB translates, then compares physical tags.
The simple VIPT design takes all index and block-offset bits from the page offset, because translation preserves those bits. This requires
With 4 KiB pages, a 32 KiB 8-way cache has 4 KiB per way and fits. A 48 KiB 12-way cache also fits. A 64 KiB 8-way cache has 8 KiB per way and needs a page-number bit for indexing, so it requires more ways or additional handling.
Keep cached mappings current
Translations belong to address spaces. A context switch can flush old entries or distinguish them with address-space identifiers, or ASIDs. Changes to mappings require the corresponding translation-cache maintenance; RISC-V provides sfence.vma. When a page is evicted from memory, its old translation must not remain usable in the TLB. The TLB holds mappings and access rights, while ordinary caches hold the program's data and instructions.
Key Takeaways
- A TLB stores translations and permissions, not program data.
- A successful page-table walk resolves a TLB miss without a page fault.
- TLB reach equals entry count times page size.
- Simple VIPT indexing fits index and block-offset bits inside the page offset.
- ASIDs and translation invalidation prevent use of mappings from the wrong address space or an old mapping.
6Write cache-aware programs
Loops and data layouts decide which bytes a processor asks for next. Follow those addresses to improve spatial locality, preserve useful data through blocking, and understand when prefetching can hide a wait. Compare row and column traversals, layouts for records, and tile footprints before measuring a change. Capacity, set conflicts, translation coverage, and memory bandwidth all help explain why a transformation works on one workload and helps less on another.
6.1 Choose loops and layouts that use each line
Cache-aware code makes fetched bytes useful before their block is evicted. Start with the addresses generated by the inner loop. Then ask which data is reused, how far apart accesses are, and whether those blocks can coexist in the cache.
Traverse arrays in storage order
C and C++ store rectangular arrays in row-major order. Adjacent columns of one row are adjacent in memory. Fortran, MATLAB, and Julia use column-major order; NumPy arrays default to row-major order. The efficient inner traversal follows the actual layout.
A C array double a[1024][1024] occupies 8 MiB. Each row takes 8192 bytes. With 64-byte cache lines, each line holds eight doubles. A row walk can use all eight before moving on, giving roughly one cold miss per eight accesses in a simple demand-fetch model.
A column walk steps 8192 bytes between consecutive accesses. It touches 1024 distinct lines before revisiting nearby data in the next column. Those lines occupy 64 KiB, exceeding a 32 KiB L1. They also conflict: in a 64-set cache, a stride of 128 lines preserves the set index. An 8-way set cannot hold 1024 competing lines.
Padding a row to 1032 doubles makes its stride 8256 bytes, or 129 lines. Successive rows then advance by one set modulo 64, spreading the requests. Padding addresses mapping conflicts; the amount of data still matters.
Interchange loops when the result is preserved
Loop interchange changes which loop runs inside another. For row-major matrix multiplication, the i, j, k order streams a row of A but a column of B. In a large streaming model with little reuse between passes, this costs about misses per inner iteration.
With i, k, j, the inner loop streams rows of B and C, while one A element is reused. Counting a fresh stream for both rows gives about misses per iteration, 4.5 times fewer. If the repeatedly updated row of C stays resident, the count approaches 0.125. Cache capacity and conflicts decide which reuse survives.
Interchange must preserve required computation behavior. Dependencies, overlapping pointers, and floating-point evaluation order can constrain transformations; compilers need proof that a change is allowed.
Fetch the fields you use
An array of structures groups all fields of one object. A structure of arrays groups one field across objects. If a particle record holds eight doubles in one 64-byte line, summing only x across one million aligned records fetches about 64 MB. A separate contiguous x array fetches about 8 MB, using every double brought in. Code using every particle field together may favor the original structure layout.
Linked nodes can be scattered, and each next address may depend on a pointer just loaded. Contiguous arrays or node pools can improve locality. Compact hot fields also let more active data fit within each level.
Measure runtime and relevant hardware counters before and after a change. Cache misses can explain a slow loop, but computation, bandwidth, or branches may be the limiting factor. Keep the input and results comparable so a speed difference reflects the change being evaluated.
Key Takeaways
- Match the inner loop to the array storage order.
- Large power-of-two strides can concentrate requests in one set.
- Padding changes mapping; compact layouts reduce the bytes fetched.
- Loop interchange must preserve required computation behavior.
- Choose arrays of structures or structures of arrays according to which fields are used.
- Measure the bottleneck and verify results when changing code.
6.2 Reuse tiles and fetch ahead
Loop interchange improves access order. Blocking, also called tiling, goes further by keeping a small region of data active until its useful reuse is complete. Prefetching moves a future transfer earlier so its delay overlaps useful work.
Keep a group of tiles resident
In blocked multiplication of square matrices, one tile of A and one tile of B contribute to one tile of C. A tile of side contains elements. Working repeatedly on these small tiles reuses data before moving to the next region.
For 8-byte doubles, three tiles require bytes. In a 32 KiB cache, the capacity limit is
Choosing a side of 32 uses 24576 bytes, or 24 KiB, leaving some space for other data. Choosing 36 merely because the arithmetic permits it leaves much less room and can expose conflicts. Capacity is a starting estimate; actual tile sizes are tuned by measurement.
A blocked traversal steps the outer loop by the tile size. Its inner bounds stop at the smaller of the tile end and matrix size. For example, if a dimension is 70 and tiles have side 32, the final tile has only six elements along that dimension. A full-size final tile would access beyond the array.
Estimate what reuse saves
In a simplified large-matrix model with 64-byte lines, the naive i, j, k order has about misses when streamed rows are no longer cached on the next pass. A blocked version can reduce this to about , assuming the three working tiles stay cached and ignoring conflicts.
For and , these estimates are about 1.2 billion and 8.4 million misses, a factor of 144. Both versions still perform about floating-point operations. The saving is in repeated data movement, not in the multiplication's arithmetic count. The model describes ideal reuse; measured speedup also depends on bandwidth, execution, and other overhead.
Prefetch early enough to hide latency
Hardware prefetchers recognize streams such as sequential or constant-stride accesses. They request lines before demand accesses need them. Software can also request advance fetches, for example with GCC or Clang's __builtin_prefetch.
The timing matters. A request made too late leaves the demand waiting. A request made too early can bring a line in only to have it evicted before use. An inaccurate request consumes bandwidth and cache space without helping the program. Pointer chasing is harder to prefetch because the next address often becomes known only after the current node arrives.
Timely prefetching can turn later demand misses into hits, but the lines still travel through the hierarchy. It hides latency rather than reducing the required payload of a streaming pass. Blocking helps when values are reused; a one-time sweep has no repeated data to retain and may already be limited by memory bandwidth.
Key Takeaways
- Blocking keeps reused tiles active while their data is useful.
- Estimate tile storage for all simultaneously needed arrays.
- Handle partial edge tiles with bounded loop limits.
- Blocking reduces data movement while preserving the arithmetic workload.
- Prefetching needs useful addresses and enough lead time; inaccurate requests waste bandwidth.
Memory Hierarchy and Caches examples
1From an array scan to a memory hierarchy
13 steps
- 1IntroductionWhy keep a small memory close?
A processor can issue work much faster than a large memory can answer every request. A cache helps when a program returns to recent data or uses nearby addresses; that reuse is called locality. Follow one array scan to see how much a single line fill can serve, then connect that reuse to the technologies and levels that supply the data, the memory hierarchy.
- 2ExplanationSeparate two kinds of locality
Temporal locality reuses an item soon: a loop body executes repeatedly, and a running total is updated each iteration. Spatial locality uses nearby addresses: a sequential array scan reads adjacent elements.
A loop can have both in its instruction stream even when every array element is read only once. Identify what is being accessed before assigning a kind of locality.
- 3ExampleHow much does one line supply?
A block-aligned array holds 1000 integers of 4 bytes each. Cache lines contain 64 bytes. Each fill supplies consecutive integers. After the first integer misses, the next 15 can hit. The last line need not be full: the 4000-byte array needs lines.
- 4ChallengePredict a smaller scan
An aligned array holds 320 four-byte integers. In a cold demand-fetch cache with 64-byte lines, no interference, and room for the array, how many array reads miss? What locality supplies the remaining hits?
---reveal---
There are 16 integers per line and lines, so 20 reads miss. The other 300 hit through spatial locality. Each element is used once; these hits do not require temporal reuse of the elements.
- 5Key InsightA working set needs usable places
The working set is the blocks used during a time window. A small active set can stay close even when the whole program is large.
Both capacity and placement matter. If two active blocks are allowed only one shared entry, they can evict each other while other entries remain empty. Register-held loop variables also need no data-cache space, even if the source reads them repeatedly.
- 6ExplanationCompare powered memory cells
SRAM holds a bit in a stable powered circuit, typically using six transistors. It needs no refresh and is fast, but costs substantial area per bit. DRAM holds charge on a capacitor; leakage requires refresh. Its denser cells make it suitable for large main memory.
Both are volatile. “Static” describes how SRAM holds its state while powered, not whether it survives a power loss.
- 7ExampleWait first, then transfer
DRAM activates a row into a bank's row buffer and serves selected columns from it. Bursts and overlapping banks increase delivery rate. They do not remove initial access delay.
With 60 ns initial latency, a 64-byte line transferred at 16 bytes/ns needs another 4 ns. Total service is about 64 ns. Most of that wait precedes the transfer, even though the interface moves bytes quickly.
- 8ExplanationChoose storage that keeps its contents
NAND flash keeps data without power. It reads and programs pages, while erasing larger blocks before programmed space can be reused. Those operations take much longer than SRAM or DRAM access.
Program/erase wear limits a block's life. Wear leveling spreads updates across blocks so frequently changed logical data does not wear out one physical location early.
- 9ChallengeDistinguish persistence and refresh
A device must keep records after power is removed. Would replacing DRAM with SRAM meet that requirement? Explain.
---reveal---
No. SRAM avoids refresh but still loses its data without power, just as DRAM does. Nonvolatile storage such as flash meets the persistence requirement. Its slower page operations and erase requirements explain why it serves a different role from on-chip cache memory.
- 10ExplanationPlace the levels in order
Registers sit closest to execution, followed by L1, L2, L3, DRAM, and storage. Caches move blocks, commonly 64 bytes, while virtual memory uses pages, commonly 4 KiB.
L1 often separates instruction and data caches so the pipeline can access both together. A miss in one level continues the search below; an L1 miss can still be an L2 hit.
- 11ExamplePrice the occasional miss
Use a simplified 1-cycle lookup, 97% hits, and a 100-cycle extra miss penalty. Every request pays the lookup, and 3% pay the penalty:
A miss costs 101 cycles here. The 100-cycle figure is additional time, so charging it as the entire miss time would omit the lookup on misses.
- 12ChallengeConnect the program with its average
Two programs use the same 1-cycle cache and 80-cycle extra penalty. One has 2% misses; the other has 20%. Find their average times and explain why identical hardware gives different results.
---reveal---
The averages are and cycles. Different access patterns produce different miss rates. The cache exploits the locality each program supplies; its capacity and technology alone do not fix the result.
- 13RecapRead an access at three scales
When examining memory behavior, identify the item being reused, the block transferred with it, and the level serving it. Locality explains likely reuse, memory technology explains cost and capacity, and hit/miss timing turns those observations into an access-time estimate. For a concrete program, begin with the actual address stream.
2Build and trace a cache lookup
15 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionAn address must answer two questions
- 2ExplanationRemove the byte offset first
- 3ExplanationCount entries before index bits
- 4ChallengeCheck a new field split
- 5ExampleAccount for the stored tag
- 6ExampleBegin with an empty cache
- 7ExampleWatch one entry change owners
- 8ExampleFinish the replacement sequence
- 9ChallengeTrace without confusing bytes and blocks
- 10ExplanationTurn entries into sets and ways
- 11ExampleTrack recency on every access
- 12ChallengeDistinguish LRU from FIFO
- 13Key InsightKnow what more ways can buy
- 14ChallengeCompare equal-capacity designs
- 15RecapCarry state through the lookup
3Diagnose a miss and preserve changed data
12 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionA miss has a cause and a service path
- 2ExplanationServe a waiting read
- 3ExplanationClassify by the right comparison
- 4ChallengeSeparate spare capacity from conflicts
- 5ConnectionChoose which cost to improve
- 6ExplanationTrack a write-back block
- 7ExplanationQueue write-through stores
- 8ExplanationSet a separate rule for write misses
- 9ChallengeFollow a store and a later read
- 10ExampleCount both directions of traffic
- 11ChallengeConnect classification with write traffic
- 12RecapKeep the decisions separate
4Calculate the cost of a hierarchy
16 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionAttach a denominator and a unit
- 2ExampleCalculate one-level AMAT
- 3TipConvert after calculating
- 4ChallengeInclude a stated complete miss time
- 5ExampleWeight the requests that exist
- 6ExampleChange from accesses to instructions
- 7ExampleFinish with runtime
- 8ChallengeIncrease the processor clock
- 9ConnectionCheck whether delays overlap
- 10ExampleKeep local and global rates distinct
- 11ExampleCompute the lower service cost
- 12ExampleReturn to the original stream
- 13ChallengeDiagnose a denominator error
- 14ExampleInsert one more conditional level
- 15ChallengeCombine cache traffic with CPI
- 16RecapChoose the correct level of accounting
5Translate an address without confusing lookups
15 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionOne address, two lookup problems
- 2ExampleFind the unchanged part
- 3ExampleUse the page-table entry
- 4ChallengeTranslate a different byte
- 5ExplanationA valid page still has access rights
- 6ExplanationHandle a missing page
- 7ExampleEstimate a flat table
- 8ExplanationReuse translations in the TLB
- 9Key InsightFollow independent hit outcomes
- 10ChallengeDecide whether storage is needed
- 11ExampleCompute translation reach
- 12ExplanationStart cache indexing during translation
- 13ChallengeCheck a proposed L1 design
- 14ConnectionRetire stale translations
- 15RecapKeep translation state and data state separate
6Make each fetched line useful
13 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionBegin with the inner loop's addresses
- 2ExampleUse all the doubles in a line
- 3ExampleSee capacity and conflicts together
- 4TipChange the row stride
- 5ChallengeChoose a layout for the access
- 6ExplanationInterchange to expose streams
- 7ExplanationKeep three tiles active
- 8ExampleLeave room beyond the capacity estimate
- 9ChallengeStop edge tiles at the array bound
- 10Key InsightDistinguish fewer transfers from less arithmetic
- 11ExplanationFetch while useful work continues
- 12ChallengeExplain a smaller-than-expected speedup
- 13RecapTest a concrete change
Memory Hierarchy and Caches practice questions
Set 1: Placement, misses, and stores10 Practice Questions
Question 1 of 10
Show answerHide answer
Question 2 of 10
Show answerHide answer
Question 3 of 10
Show answerHide answer
Question 4 of 10
Show answerHide answer
Question 5 of 10
0x80 is followed by a read of 0x80, with no intervening accesses. What happens at this cache?Show answerHide answer
Question 6 of 10
Show answerHide answer
Question 7 of 10
Show answerHide answer
Question 8 of 10
Show answerHide answer
Question 9 of 10
0x00, 0x04, 0x20, and 0x24, then a read of 0x40. Counting fills and victim write-backs only, how many bytes move between this cache and the next level?Show answerHide answer
Question 10 of 10
Show answerHide answer
Set 2: Memory behavior and cache lookup10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
0x2B6, which pair gives the entry index and byte offset?Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
0x00, 0x07, 0x10, 0x04, in that order. What is the hit rate?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
0x24, 0x28, 0x64, 0x34, 0x2C, 0x68. What hit rate and final block at index 2 result?Show answerHide answer
Save this lesson to see this answer.
Set 3: Access time and program speed10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
Show answerHide answer
Save this lesson to see this answer.
Set 4: Pages, TLBs, and cache indexing10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
0x12345 maps to physical page number 0x2A. What is the physical byte address?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
0x0000, 0x1000, 0x2000, 0x3000, 0x4000, in that order. All pages are resident. What happens after warm-up?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
Show answerHide answer
Save this lesson to see this answer.
Set 5: Code changes and hierarchy trade-offs10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
a[i][j]?Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
Show answerHide answer
Save this lesson to see this answer.
Stuck on your own question? Homework Help
Key Terms
A
Amdahl's law
Array of structures
ASID
Average memory access time
B
Bandwidth
Base CPI
Block offset
Blocking
Byte addressing
C
Cache hit
Cache index
Cache line
Cache miss
Cache pollution
Cache trace
Capacity miss
Clock cycle time
Coherence miss
Compulsory miss
Conflict miss
Critical word first
D
Direct-mapped cache
Dirty bit
DRAM
E
Early restart
F
FIFO replacement
Fully associative cache
G
Global miss rate
H
Hit rate
Hit time
L
Latency
Local miss rate
Locality
Loop interchange
LRU replacement
M
Memory bank
Memory hierarchy
Memory-stall CPI
Miss penalty
Miss rate
Multilevel cache
N
NAND flash
No-write-allocate
Nonblocking cache
P
Padding
Page fault
Page frame
Page offset
Page table entry
Page-table walk
Physical page number
Prefetching
Pseudo-LRU
R
Refresh
Row buffer
Row-major order
a[i][j], varying j in the inner loop walks adjacent elements of one row.S
Set-associative cache
Spatial locality
SRAM
Stride
Structure of arrays
T
Tag
Temporal locality
Thrashing
Tile footprint
TLB
TLB reach
Translation invalidation
sfence.vma to coordinate translation-cache state with mapping updates.V
Valid bit
VIPT cache
Virtual memory
Virtual page number
W
Way
Wear leveling
Weighted miss rate
Working set
Write buffer
Write-allocate
Write-back
Write-through
About this lesson
Make your own Study Materials
Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.