G27
Self-checkedTier 1 13 min readcoa.cache-replacement-write

Cache replacement and write policies

What the cache does when a set is full (LRU, FIFO, random, optimal) and when the processor writes (write-through, write-back, allocate or not), the dirty bit, memory traffic, and why more cache lines can mean more misses under FIFO.

Why it exists

Two decisions have to be made on every cache access that does not simply hit. When a block must be brought in and every line of its set is occupied, which line is thrown out? And when the processor writes, is memory updated at once, later, or only when the line is replaced? The first is the replacement policy, the second the write policy. They decide how often the cache misses, how much memory traffic it creates, and whether the memory ever holds stale data. GATE asks for the number of misses of a sequence under a policy, the contents of the cache after some accesses, the number of memory writes, and the properties of the policies.

Prerequisites

You need the structure of the cache (sets, ways, tag, valid bit) from cache mapping.

Precise definitions

Replacement is needed only when the set is full. In a direct-mapped cache there is no choice (one line per set); in a set-associative or fully associative cache one of the WW lines of the set must be chosen. A free (invalid) line is always used first.

Policies.

  • LRU (least recently used): replace the block that has gone unused for the longest time; exploits temporal locality. Needs the order of use: counters or an ordered list per set; true LRU is costly for large associativity, so hardware often uses an approximation (pseudo-LRU).
  • FIFO (first in, first out): replace the block that has been in the set longest, regardless of use. Simple (a pointer or a queue), a hit does not change the order.
  • Random: replace a random line. Very cheap; performs about as well as the others for large caches.
  • LFU (least frequently used): replace the block with the fewest accesses.
  • Optimal (OPT, Belady's MIN): replace the block whose next use is farthest in the future. It needs knowledge of the future so it cannot be built, but it gives the fewest possible misses and is the yardstick.

Properties. For any sequence, OPT misses no more than any other policy. LRU and OPT have the stack (inclusion) property: the contents of a cache with kk lines are always contained in the contents of a cache with k+1k + 1 lines, so more lines never produce more misses. FIFO does not: on some sequences a bigger cache has more misses (Belady's anomaly).

Write policies on a hit.

  • Write-through: every write goes to the cache and to memory. Memory is always up to date, so a replaced block can simply be dropped; but every write costs a memory write (a write buffer hides the delay).
  • Write-back (copy-back): a write updates only the cache and sets the line's dirty bit. The block is written to memory only when it is replaced (and only if dirty). Fewer memory writes (many writes to one block become one), but memory may be stale and the replacement of a dirty block costs a write-back.

Write policies on a miss.

  • Write-allocate: bring the block into the cache first, then write as on a hit.
  • No-write-allocate (write-around): write directly to memory and do not load the block.

Usual pairings. Write-back with write-allocate (locality of writes pays off) and write-through with no-write-allocate (nothing is gained by loading a block that will only be written).

Memory traffic. Count in blocks or words as the question says. Reads: one block fill per miss that allocates a line. Writes: write-through, one memory write per store (hit or miss); write-back, one block write per dirty replacement.

How it works

The reference string 1 2 3 4 1 2 5 1 2 3 4 5 (block numbers) in a fully associative cache of 3 lines. Step through all three policies. FIFO throws out the oldest block even if it is about to be used again; LRU throws out the one not used for the longest time; the optimal policy looks ahead. The final counts are 9 misses for FIFO, 10 for LRU and 7 for OPT. (LRU is not always better than FIFO: on this string it is worse.)

FIFO replacement, 3 lines (fully associative): start

Cache simulated, not typed

1 set x 3 ways, FIFO. Hit time 1, miss penalty 10 cycles.

hits
0
misses
0
hit rate
-
avg cycles per access
-
memory reads
0
memory writes
0
setway 0way 1way 2
0emptyemptyempty

Step 1

Three lines, fully associative, FIFO replacement: the block that has been in the cache longest is replaced, whether or not it is still being used. The reference string is the blocks 1 2 3 4 1 2 5 1 2 3 4 5.

1 / 13
computed by script: exact simulation of the cache, one access per step. python3 scripts/gen-coa-mem-traces.py

LRU replacement, 3 lines (fully associative): start

Cache simulated, not typed

1 set x 3 ways, LRU. Hit time 1, miss penalty 10 cycles.

hits
0
misses
0
hit rate
-
avg cycles per access
-
memory reads
0
memory writes
0
setway 0way 1way 2
0emptyemptyempty

Step 1

The same reference string with LRU: the block that has not been used for the longest time is replaced.

1 / 13
computed by script: exact simulation of the cache, one access per step. python3 scripts/gen-coa-mem-traces.py

Optimal replacement, 3 lines (fully associative): start

Cache simulated, not typed

1 set x 3 ways, OPT. Hit time 1, miss penalty 10 cycles.

hits
0
misses
0
hit rate
-
avg cycles per access
-
memory reads
0
memory writes
0
setway 0way 1way 2
0emptyemptyempty

Step 1

The same string with the optimal policy, which looks ahead and replaces the block whose next use is farthest in the future. It cannot be built (it needs the future) but it is the best possible and a yardstick for real policies.

1 / 13
computed by script: exact simulation of the cache, one access per step. python3 scripts/gen-coa-mem-traces.py

The write policies on a small direct-mapped cache of 4 lines with the operations: write 0, 1, 2, 3 (four writes to one block), read 16 (a different block that maps to the same line), read 0. First write-through with no-write-allocate (4 memory writes, 2 block reads) and then write-back with write-allocate (1 memory write, 3 block reads).

Write-through with no-write-allocate (direct mapped, 4 lines): start

Cache simulated, not typed

4 sets x 1 way, direct mapped, write-through, no-write-allocate. Hit time 1, miss penalty 10 cycles.

hits
0
misses
0
hit rate
-
avg cycles per access
-
memory reads
0
memory writes
0
setway 0
0empty
1empty
2empty
3empty

Step 1

A direct-mapped cache with 4 lines of 4 bytes, write-through and no-write-allocate: every write goes to memory at once, and a write that misses does not bring the block into the cache.

1 / 7
computed by script: exact simulation of the cache, one access per step. python3 scripts/gen-coa-mem-traces.py

Write-back with write-allocate (direct mapped, 4 lines): start

Cache simulated, not typed

4 sets x 1 way, direct mapped, write-back, write-allocate. Hit time 1, miss penalty 10 cycles.

hits
0
misses
0
hit rate
-
avg cycles per access
-
memory reads
0
memory writes
0
setway 0
0empty
1empty
2empty
3empty

Step 1

The same cache, write-back and write-allocate: a write that misses first loads the block, writes go only to the cache and set the dirty bit D, and memory is updated only when a dirty block is replaced.

1 / 7
computed by script: exact simulation of the cache, one access per step. python3 scripts/gen-coa-mem-traces.py

Worked examples

EX 1Replacement and write traffic in a program

Easy
#include <stdio.h>
#include <string.h>
 
#define N 12
static const int seq[N] = { 1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5 };
 
/* fully associative cache of `frames` lines; policy 0 = FIFO, 1 = LRU, 2 = optimal */
static int misses(int policy, int frames) {
    int blk[8], stamp[8], n = 0, miss = 0;
    for (int i = 0; i < N; i++) {
        int hit = -1;
        for (int k = 0; k < n; k++) if (blk[k] == seq[i]) hit = k;
        if (hit >= 0) {
            if (policy == 1) stamp[hit] = i;                     /* LRU remembers the last use */
            continue;
        }
        miss++;
        if (n < frames) { blk[n] = seq[i]; stamp[n] = i; n++; continue; }
        int victim = 0;
        if (policy == 2) {                                       /* optimal: the block used farthest in the future */
            int far = -1;
            for (int k = 0; k < n; k++) {
                int next = N + 1;
                for (int j = i + 1; j < N; j++) if (seq[j] == blk[k]) { next = j; break; }
                if (next > far) { far = next; victim = k; }
            }
        } else {                                                 /* FIFO: oldest load time, LRU: oldest use (the stamp) */
            for (int k = 1; k < n; k++) if (stamp[k] < stamp[victim]) victim = k;
        }
        blk[victim] = seq[i]; stamp[victim] = i;
    }
    return miss;
}
 
/* memory traffic of the write policies on a direct-mapped cache of 4 lines of 4 bytes */
static void traffic(int write_back) {
    long blk[4] = { -1, -1, -1, -1 };
    int dirty[4] = { 0, 0, 0, 0 }, reads = 0, writes = 0;
    struct { char op; int addr; } ops[6] = { {'W', 0}, {'W', 1}, {'W', 2}, {'W', 3}, {'R', 16}, {'R', 0} };
    for (int i = 0; i < 6; i++) {
        long b = ops[i].addr / 4;
        int line = (int)(b % 4);
        int hit = blk[line] == b;
        if (!hit && ops[i].op == 'W' && !write_back) { writes++; continue; }     /* write-through, no-write-allocate */
        if (!hit) {
            if (dirty[line]) writes++;                                           /* write the dirty victim back */
            reads++;
            blk[line] = b; dirty[line] = 0;
        }
        if (ops[i].op == 'W') { if (write_back) dirty[line] = 1; else writes++; }
    }
    printf("%-34s memory reads %d, memory writes %d\n", write_back ? "write-back, write-allocate:" : "write-through, no-write-allocate:", reads, writes);
}
 
int main(void) {
    printf("frames  FIFO  LRU  OPT\n");
    for (int f = 1; f <= 6; f++) printf("%6d  %4d  %3d  %3d\n", f, misses(0, f), misses(1, f), misses(2, f));
    printf("FIFO with 3 frames: %d misses, with 4 frames: %d misses (Belady's anomaly)\n", misses(0, 3), misses(0, 4));
    traffic(0);
    traffic(1);
    return 0;
}
frames  FIFO  LRU  OPT
     1    12   12   12
     2    12   12    9
     3     9   10    7
     4    10    8    6
     5     5    5    5
     6     5    5    5
FIFO with 3 frames: 9 misses, with 4 frames: 10 misses (Belady's anomaly)
write-through, no-write-allocate:  memory reads 2, memory writes 4
write-back, write-allocate:        memory reads 3, memory writes 1

Reading it. With 3 frames: FIFO 9, LRU 10, OPT 7. With 4 frames FIFO gets worse (10) while LRU improves (8) and OPT improves (6): this is Belady's anomaly. With 5 frames all policies miss only 5 times (one for each distinct block). The write-through cache did 4 memory writes and 2 block reads; the write-back cache did 1 memory write (the dirty block when it was replaced) and 3 block reads (it also loaded the block on the first write miss).

EX 2Which block is replaced?

Easy

A 2-way set holds blocks A (loaded first, last used at time 8) and B (loaded second, last used at time 5). A new block C maps to the set. FIFO replaces A (loaded first) even though it was used most recently; LRU replaces B (the least recently used); OPT replaces whichever of A and B is needed later than the other (or never).

EX 3Count the misses by hand

Medium

String 2 3 2 1 5 2 4 5 3 2 5 2 with 3 lines, LRU: 2 miss, 3 miss, 2 hit, 1 miss (cache {2, 3, 1}), 5 miss (replace the LRU, 3: {2, 1, 5}), 2 hit, 4 miss (replace 1: {2, 5, 4}), 5 hit, 3 miss (replace 2: {5, 4, 3}), 2 miss (replace 4: {5, 3, 2}), 5 hit, 2 hit. Total: 7 misses, 5 hits. With FIFO the same string gives 9 misses and with the optimal policy 6 (the answer differs between policies; always simulate the stated policy).

EX 4Write traffic for a sequence

Medium

Direct-mapped cache, the operations W(0) W(1) W(2) W(3) R(16) R(0) with 4-byte blocks (addresses 0 to 3 form block 0, address 16 is block 4, which maps to the same line as block 0). Write-through, no-write-allocate: the four writes all miss (nothing is cached) and go to memory: 4 writes; the two reads load blocks 4 and 0: 2 reads. Write-back, write-allocate: the first write loads block 0 (1 read) and marks it dirty; the next three writes are hits (no memory traffic); the read of 16 replaces the dirty block 0, writing it back (1 write) and loading block 4 (read 2); the read of 0 replaces clean block 4 (read 3). Total: 3 reads and 1 write.

EX 5Cost of the dirty bit

GATE level

A write-back cache with 1024 lines needs one dirty bit per line: 1024 bits (a few percent of the tag store). A write-through cache needs none, because memory always has the data. On replacement a clean line is simply dropped; a dirty one is first written back, so a miss that replaces a dirty line takes about twice as long. If 30% of replaced lines are dirty, each miss costs on average 1+0.3=1.31 + 0.3 = 1.3 block transfers instead of 1 for the read.

EX 6Does more cache always help?

GATE level

For LRU and OPT the answer is yes (stack property). For FIFO the answer is no in general: the string above with 3 frames gives 9 misses and with 4 frames gives 10. This is a property of the policy (FIFO ignores recent use), not of the string being unusual; the same behaviour appears for page replacement in operating systems (page replacement).

Cheat box

Cheat box

  • Replacement only when the set is full; use free lines first. Direct mapped: no choice.
  • LRU: oldest use. FIFO: oldest load; hits do not reorder. Random. OPT: farthest next use (unrealisable, the best possible).
  • OPT ≤\le every other policy. LRU and OPT: more lines never hurt. FIFO: Belady's anomaly.
  • Write-through: memory updated on every write; no dirty bit; write buffer.
  • Write-back: dirty bit; memory updated when a dirty line is replaced.
  • Write-allocate: load the block on a write miss. No-write-allocate: write to memory only.
  • Pairs: write-back + write-allocate, write-through + no-write-allocate.
  • Traffic: one block read per allocating miss; write-through one write per store; write-back one write per dirty eviction.

Traps and GATE patterns

Connections

The set structure and the address fields are in cache mapping, and the time cost of misses and write-backs is in cache performance. Exactly the same policies and Belady's anomaly appear when the "cache" is main memory and the blocks are pages: page replacement.

PYQs

6 previous year questions from your book. I re-solved each one myself (3 by running or simulating, 3 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2024 · MSQQ9 · page 496 of the book
Consider
two
set-associative
cache
memory
architectures: WBC, which uses the write back
policy, and WTC, which uses the write through
policy. Both of them use the LRU (Least Recently
Used) block replacement policy. The cache memory
is connected to the main memory. Which of the
following statements is/are TRUE?
  • (a)A read miss in WBC never evicts a dirty block
  • (b)A read miss in WTC never triggers a write back operation of a cache block to main memory
  • (c)A write hit in WBC can modify the value of the dirty bit of a cache block
  • (d)A write miss in WTC always writes the victim cache block to main memory before loading the missed block to the cache
GATE 2022 · MSQQ13 · page 497 of the book
Let WB and WT be two set associative cache
organizations that use LRU algorithm for cache
block replacement. WB is a write back cache and
WT is a write through cache. Which of the
following statements is/are FALSE?
  • (a)Each cache block in WB and WT has a dirty bit.
  • (b)Every write hit in WB leads to a data transfer from cache to main memory.
  • (c)Eviction of a block from WT will not lead to data transfer from cache to main memory.
  • (d)A read miss in WB will never lead to eviction of a dirty block from WB.
GATE 2021 · MCQQ14 · page 497 of the book
Assume a two-level inclusive cache hierarchy, L1
and L2, where L2 is the larger of the two. Consider
the following statements.
S1: Read misses in a write through L1 cache do not
result in writebacks of dirty lines to the L2
S2: Write allocate policy must be used in
conjunction with write through caches and no-write
allocate policy is used with writeback caches.
Which of the following statements is correct?
  • (a)S1 is true and S2 is false
  • (b)S1 is false and S2 is true
  • (c)S1 is true and S2 is true
  • (d)S1 is false and S2 is false
GATE 2017 · NATQ26 · page 499 of the book
Consider a 2-way set associative cache with 256
blocks and use LRU replacement, initially the
cache is empty. Conflict misses are those misses
which occur due to the contention of multiple
blocks for the same cache set. Compulsory misses
occur due to first time access to the block. The
following sequence of accesses to memory blocks.

{0,128,256,128,0,128,256,128,1,129,257,129,1,12
9,257,129}

is repeated 10 times. The number of conflict
misses experienced by the cache is
.
GATE 2009 · MCQ · 2 marksQ44 · page 502 of the book
Consider a 4-way set associative cache (initially
empty) with total 16 cache blocks. The main
memory consists of 256 blocks and the request
for memory blocks are in the following order:
0,255,1,4,3,8,133,159,216,129,63,8,48,32,73,92,155.
Which one of the following memory block will
NOT be in cache if LRU replacement policy is
used?
  • (a)3
  • (b)8
  • (c)129
  • (d)216
GATE 2005 · MCQ · 2 marksQ60 · page 506 of the book
Consider a 2-way set associative cache memory
with 4 sets and total 8 cache blocks (0–7) and
main memory with 128 blocks (0–127). Which
memory blocks will be present in the cache after
the following sequence of memory block
references if LRU policy is used for cache block
replacement? If initially the cache did not have
any memory block from the current job?

0 5 3 9 7 0 16 55
  • (a)0 3 5 7 16 55
  • (b)0 3 5 7 9 16 55
  • (c)0 5 7 9 16 55
  • (d)3 5 7 9 16 55

Self-check

Question 1

A fully associative cache has 3 lines, initially empty, and the block references are 1 2 3 1 4 2. How many misses under LRU and under FIFO?

Show answer

LRU: 1 m, 2 m, 3 m, 1 h, 4 m (replace 2, the LRU), 2 m (replace 3): 5 misses. FIFO: 1 m, 2 m, 3 m, 1 h, 4 m (replace 1), 2 h (2 is still there): 4 misses.

Question 2

A write-back cache writes the same word 10 times and the block is then replaced. How many memory writes does the block cause, and how many for write-through?

Show answer

Write-back: 1 (at replacement, since the line is dirty). Write-through: 10.

Question 3

Which policy can never be worse than any other on any sequence, and why can it not be built?

Show answer

The optimal policy (replace the block used farthest in the future). It needs knowledge of future accesses.

Question 4

After a write miss under no-write-allocate, is the written block in the cache?

Show answer

No; the word goes straight to memory and the cache is unchanged.

Revision card

One-screen revision

  • LRU: least recently used. FIFO: oldest loaded, ignores hits. OPT: farthest next use, best, unrealisable.
  • FIFO can have Belady's anomaly (3 frames 9 misses, 4 frames 10 on 1 2 3 4 1 2 5 1 2 3 4 5); LRU and OPT cannot.
  • Write-through: every write to memory. Write-back: dirty bit, write on replacement.
  • Allocate: load on write miss. No-allocate: write to memory only.

References

  • ·Hennessy and Patterson, Computer Organization and Design, Chapter 5 Large and Fast (handling cache writes, replacement)
  • ·Hamacher, Vranesic, Zaky, Computer Organization, 5th ed., Chapter 8 The Memory System (replacement algorithms, write-through and write-back)
  • ·Silberschatz, Galvin, Gagne, Operating System Concepts, Chapter 10 Virtual Memory (page replacement, Belady's anomaly)

Verification

The FIFO, LRU and optimal runs on the string 1 2 3 4 1 2 5 1 2 3 4 5 and both write-policy runs are exact simulations re-run independently in tests/coa-mem-traces.test.ts (results, memory reads and writes and the cache contents after every access). The miss-count table for 1 to 6 frames, the stack property of LRU and the optimal policy (checked on thousands of random strings), the bound OPT <= LRU and FIFO, Belady's anomaly for FIFO, and the write-traffic rules are checked in scripts/enum-checks/coa_mem.py and by the C program (npm run verify:c). Real caches use approximations of LRU (pseudo-LRU) which are not modelled. Textbook chapter titles are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand (long C programs were not re-read line by line: they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose). No defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never