5.4.1 · HinglishMemory Hierarchy & Caches

Principle of locality (temporal - spatial)

2,603 words12 min readRead in English

5.4.1 · Hardware › Memory Hierarchy & Caches

Overview

Principle of locality ek fundamental observation hai ki programs kisi bhi given time pe apne address space ke relatively chhote hisse ko access karte hain. Yeh predictable access pattern hi poori wajah hai ki cache hierarchies kaam karti hain — locality ke bina, caching bilkul bekar hoti.

Agar programs memory ko randomly access karte, toh har access equally likely hoti. Lekin real programs mein structure hota hai, aur structure se predictability aati hai.


Do Tarah Ki Locality

Temporal Locality

Yeh kyun hota hai:

  1. Loop counters: for(int i=0; i<n; i++) — variable i har iteration mein access hota hai
  2. Function calls: Same function code kai baar execute hota hai
  3. Frequently-used variables: Accumulators, status flags, pointers

Time scale: Human terms mein milliseconds se seconds, CPU terms mein thousands se millions of cycles.

jahan aur same address ke accesses hain.

Short reuse distance = strong temporal locality.

Derivation ki yeh caching ke liye kyun matter karta hai:

Maano ek cache blocks hold karta hai. Agar address ka reuse distance hai:

  • Agar : re-reference hote waqt cache mein hi hai → cache hit
  • Agar : evict ho gaya → cache miss

Temporal locality ke liye hit rate hai:

Isliye bade caches zyada temporal locality capture karte hain — wo longer reuse distances wale blocks hold kar sakte hain.

Spatial Locality

Yeh kyun hota hai:

  1. Sequential instruction execution: Address 0x1000 par instruction ke baad 0x1004 aata hai
  2. Array traversal: a[0], a[1], a[2], ... memory mein contiguous hote hain
  3. Struct field access: Struct ke fields adjacent hote hain
  4. Stack operations: Push/pop nearby stack addresses access karte hain

jahan -va memory address hai jo access hua.

Stride = 1 word → perfect spatial locality (sequential access) Stride = 0 → pure temporal locality (same location) Large stride → poor spatial locality (idhar udhar jump karna)

Cache block benefit ki derivation:

Ek cache block bytes hold karta hai. Jab hum address fetch karte hain, toh hume milta hai.

Agar program se start hoke consecutive addresses access karta hai (stride 1), toh hum ek miss dete hain lekin hits paate hain:

Jaise jaise ( word size hai), hit rate .

Example: 64-byte cache block, 16 consecutive words (4 bytes each) access karte hue:

  • words, bytes = 16 words
  • Hit rate =

Isliye bade cache blocks spatial locality ko better exploit karte hain — lekin ek limit tak hi (agar stride bada hai, toh hum bekar data fetch karte hain).


Saath Kaam Karna: The Locality Combo

int sum = 0;                // sum in register
for (int i = 0; i < 1000; i++) {
    sum += array[i];
}

Temporal locality:

  • Variable sum: 1000 baar access hota hai (padhna, uspe add karna, store karna)
  • Variable i: 1000 baar access hota hai
  • Loop instructions khud: 1000 baar execute hote hain

Spatial locality:

  • array[0], array[1], array[2], ... memory mein contiguous hain
  • array[0] fetch karne se array[1..15] cache block mein aa jaata hai (agar 64-byte blocks hain, 4-byte ints ke saath)
  • Stride = 4 bytes (ek integer)

Har step kyun matter karta hai:

  1. Pehli iteration: array[0] par cache miss, array[0..15] wala block load hota hai
  2. Agle 15 iterations: array[1..15] par Cache hits — spatial locality kaam aati hai
  3. 16vi iteration: array[16] par cache miss, array[16..31] load hota hai
  4. Pattern repeat hota hai

Total misses = misses 1000 accesses ke liye → hit rate 93.7% sirf spatial locality se.

Temporal locality add karo: sum, i, aur loop code cache mein (ya registers mein) rehta hai → un sab ka hit rate ~100% hota hai.

// Row-major storage: A[i][j] at memory address &A + (i*N + j)*sizeof(int)
for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
        for (int k = 0; k < N; k++) {
            C[i][j] += A[i][k] * B[k][j];
        }
    }
}

Access patterns:

  • A[i][k]: Row ko sequentially access karta hai → good spatial locality (stride = 1 element)
  • B[k][j]: Column access karta hai → stride = elements (rows ke across jump karta hai)
    • Agar , stride = 4000 bytes (4-byte ints maano)
    • Cache block 64 bytes ka hai → har block fetch mein sirf 1 element use hota hai
    • Terrible spatial locality: fetched data ka sirf 1/16 = 6.25% utilization

Yeh step itna bura kyun hai:

  • Har B[k][j] access cache mein miss karta hai
  • Hum 64 bytes fetch karte hain lekin sirf 4 bytes use karte hain
  • Bandwidth waste hoti hai, performance gir jaati hai

Fix: Pehle ko transpose karo, ya blocking use karo (cache optimization mein cover hoga).


Locality Quantify Karna: The 90/10 Rule

Yeh physics ka law nahi hai — yeh real workloads mein ek statistical observation hai.

Kyun?

  • Loops execution time dominate karte hain (inner loops millions of times execute hote hain)
  • Hot functions baar baar call hote hain
  • Cold code (error handlers, initialization) rarely run karta hai

Derivation:

Maano ek program instructions wala hai, jahan fraction "hot" hai (loops mein / frequently called).

Agar hot instructions average par baar execute hote hain, aur cold instructions ek baar:

jahan time per instruction hai.

Hot code mein time ka fraction:

90/10 rule ke liye: , solve karo:

Toh agar 10% code average par ~81 baar execute hota hai, toh 90/10 rule milta hai.

Cache implication: Agar tum us 10% code aur uske data ko cache mein rakh sako, toh tumne 90% execution time optimize kar liya.


Common Mistakes & Misconceptions

Yeh galat kyun hai: Yeh toh temporal locality hai! Spatial ka matlab hai nearby addresses access karna (alag addresses, lekin address space mein close).

Steel-man: Confusion isliye hota hai kyunki dono cache performance improve karte hain, aur practice mein yeh aksar saath hote hain (jaise array pe loop karne mein dono hote hain). Lekin mechanisms alag hain:

  • Temporal: Reuse ke liye same block ko cache mein rakho
  • Spatial: Adjacent blocks prefetch karo kyunki wo jald chahiye honge

Fix: Etymology yaad rakho: "Temporal" = time (same address over time), "Spatial" = space (address space mein nearby).

Yeh galat kyun hai: Agar tumhara stride bada hai ya access pattern random hai, toh tum bekar data fetch karte ho. Bade blocks ka matlab yeh bhi hai:

  • Fewer blocks cache mein fit hote hain (fixed cache size ke liye) → worse temporal locality
  • Higher miss penalty (zyada bytes transfer karne padte hain)
  • Conflict misses badhte hain (fewer blocks = zyada collisions)

Example:

  • Cache size = 32 KB
  • Block size = 16 bytes → 2048 blocks
  • Block size = 256 bytes → 128 blocks

Agar tumhara working set 500 distinct blocks ka hai jo good temporal locality rakhte hain, toh 16-byte blocks jeetenge (sab 500 hold kar sakte hain), lekin 256-byte blocks sirf 128 hold kar sakte hain → bahut saari evictions.

Fix: Optimal block size stride distribution aur working set size par depend karta hai. Typical sweet spot: 32-128 bytes.


Locality Memory Hierarchy Ko Kyun Enable Karti Hai

Agar yeh bets pay off hoti hain, toh tumhe milta hai:

  • Fast memory (cache) mein frequently used data hota hai
  • Slow memory (DRAM) mein baaki sab hota hai
  • Average access time cache speed ke paas pahunchta hai, DRAM speed ke nahi

Average access time ki derivation:

Maano = hit rate (accesses ka fraction jo cache mein hain), = cache access time, = DRAM access time.

Dono terms kyun? Cache pehle check hota hai (hamesha pay karo), phir miss par bhi pay karna padta hai.

Simplify karo:

Example: ns, ns, :

DRAM se ~17× faster (jisko ns per access chahiye) — yeh sab sirf isliye kyunki locality banati hai.

Agar locality nahi (), ns → cache bekar overhead hai.


Connections

  • Cache organization fundamentals — caches locality ko blocks aur replacement policies ke zariye kaise exploit karti hain
  • Cache mapping strategies — direct-mapped vs. set-associative, temporal vs. spatial conflicts ka trade-off
  • Working set model — locality ko "recently used pages" ke roop mein formalize karna
  • Loop blocking and tiling — locality improve karne ke liye compiler transformations
  • Virtual memory — poore address space mein locality demand paging enable karti hai

Recall Ek 12-saal ke bachchhe ko explain karo

Socho tumhara desk tumhara cache hai, aur kamre ke doosri taraf bookshelf main memory hai. Jab tum homework kar rahe ho:

Temporal locality: Tum baar baar same pencil use karte rehte ho. Har baar shelf tak jaane ki bajaye, tum use desk par hi chhod dete ho kyunki jaante ho 30 second baad phir chahiye hogi. Yahi temporal hai — "maine abhi yeh use kiya, shaayad jald phir use karunga."

Spatial locality: Jab tum shelf se math ki textbook uthate ho, saath mein math notebook bhi uthate ho kyunki wo usike paas hai, aur thodi der mein chahiye hogi. Yahi spatial hai — "agar mujhe yeh cheez chahiye, toh shaayad iske paas wali cheezein bhi chahiye hongi."

Cache bhi aise hi kaam karti hai. Computer haal hi mein use ki gayi cheezon ko paas rakhta hai (temporal) aur nearby cheezein saath mein uthata hai (spatial) kyunki programs aisa hi karte hain — wo random nahi hote, wo patterns follow karte hain jaise tum homework karte waqt karte ho.


Space → Spatial SPACE aur ADJACENCY ke baare mein hai (nearby addresses)

Simply: "Temporal = Time, Spatial = Space"


#flashcards/hardware

Principle of locality kya hai?
Yeh observation ki programs kisi bhi time pe apne address space ke chhote hisse ko predictable patterns (temporal aur spatial) mein access karte hain.
Temporal locality define karo
Agar koi memory location reference ki gayi hai, toh usse jald hi phir reference kiya jaayega. "Recently used → likely to be used again."
Spatial locality define karo
Agar koi memory location reference ki gayi hai, toh nearby locations ko bhi jald hi reference kiya jaayega. "X access karo → X+1, X+2... access hone ki sambhavna hai."
Reuse distance kya hota hai?
Same address ke do references ke beech distinct memory accesses ki count. Short reuse distance = strong temporal locality.
Memory accesses mein stride kya hota hai?
Consecutive memory addresses ke beech ka difference: |A_{i+1} - A_i|. Stride=1 word → good spatial locality, large stride → poor.
Bade cache blocks spatial locality ko kyun help karte hain?
Ek miss B bytes fetch karta hai; agar k consecutive addresses access karo, toh hit rate = (k-1)/k. Zyada bytes per block = zyada hits per miss.
Loops temporal locality kyun create karte hain?
Loop bodies (instructions aur counters jaise variables) baar baar execute hote hain, same memory locations ko kai baar access karte hain.
Arrays spatial locality kyun create karte hain?
Array elements memory mein contiguously store hote hain, isliye a[i] access karne ka matlab hai a[i+1] nearby hai aur agla access hone ki sambhavna hai.
90/10 rule kya hai?
Programs apna 90% execution time 10% code mein spend karte hain (hot loops aur frequently-called functions).
Average memory access time formula
T_avg = T_cache + (1 - hit_rate) × T_memory. Cache pehle check hota hai, miss par dono costs pay karni padti hain.
Bade cache blocks performance kyun hurt kar sakte hain?
(1) Fewer blocks fit hote hain → evictions se worse temporal locality, (2) Higher miss penalty, (3) Agar stride bada ho toh bandwidth waste hoti hai.
Agar program mein koi locality nahi toh kya hota hai?
Caches bekar ho jaati hain. Hit rate ≈ 0, isliye average access time slow DRAM time plus cache overhead ke barabar ho jaata hai.

Concept Map

creates predictability

flavor 1

flavor 2

recently used, used again

nearby used soon

measured by

measured by

d less than C

stride 1 = sequential

enabled by

captures longer d

Principle of Locality

Program Structure

Temporal Locality

Spatial Locality

Reuse Distance

Stride

Cache Hierarchy

Cache Hits

Larger Caches