5.4.16 · D2 · HinglishMemory Hierarchy & Caches

Visual walkthroughMemory consistency models

2,218 words10 min read↑ Read in English

5.4.16 · D2 · Hardware › Memory Hierarchy & Caches › Memory consistency models

Parent: Memory consistency models · Hinglish: यह Hinglish में पढ़ो →

Hum assume karte hain ki aapne kabhi store buffer, "reordering", ya arrows S→L nahi dekhe. Hum har cheez khud earn karte hain.


Step 1 — "Memory" do cores ko kaisi dikhti hai

KYA. Machine draw karo. Do chhote processors (hum inhe core kehte hain — ek independent instruction-runner) ek shared memory ke box ke upar baithe hain. Memory bas numbered mailboxes ki ek wall hai; unme se do ka naam x aur y hai, dono 0 se shuru hote hain.

YAHAN SE KYU SHURU KAREIN. Isse pehle ki hum kahein "load ne stale value padhi," hume agree karna hoga ki values kahan rehti hain aur kaun unhe dekh sakta hai. Ek value "core ko visible" tabhi hoti hai jab woh shared memory wall tak pahunch jaaye — jab tak woh core ke andar baitha ho tab nahi. Yahi distinction poori kahani hai, isliye hum ise pehle picture karte hain.

PICTURE. Do cores magenta aur violet mein; shared memory wall beech mein x=0, y=0 hold karte hue.

Figure — Memory consistency models

Step 2 — Har core jo program run karta hai (litmus test)

KYA. Har core ko do instructions do. Yeh exact 4-instruction pattern Store Buffering test hai (a.k.a. Dekker).

Har symbol ko uski jagah padhte hue:

  • — Core 1 ka Store: mailbox x mein 1 daalo.
  • — Core 1 ka Load: mailbox y ki current value ko Core 1 ke private slot r1 mein copy karo.
  • , — Core 2 par mirror image: y likho, phir x padho.

YEH CHAAR KYU. Har core apna khud ka variable likhta hai, phir doosre ka padhta hai. Toh har core ka jawab (r1, r2) ek snapshot hai ki "kya doosre core ki write memory tak pahunchi thi?" Isse result ka pair ordering ka direct probe ban jaata hai.

PICTURE. Do programs side by side, (store) orange mein tinted aur (load) violet mein tinted, arrows dikhate hue ki har instruction kaun sa mailbox touch karta hai.

Figure — Memory consistency models
Recall Forecast

Aage padhne se pehle predict karo: kya hum r1 == 0 aur r2 == 0 ke saath finish kar sakte hain? Naive single-timeline reasoning ::: kehta hai nahi — ek store pehle hona chahiye, toh uska reader use miss nahi kar sakta.


Step 3 — Naive "one timeline" wali duniya (Sequential Consistency)

KYA. Ek single global clock imagine karo. Kisi bhi core ki har instruction ek single timeline par thread ki jaati hai, aur har core ki do instructions apna program order rakhti hain. Yahi Sequential Consistency (SC) hai.

PEHLE STRONG MODEL KYU PICTURE KAREIN. Yeh feel karne ke liye ki real hardware humein kyun surprise karta hai, hum pehle woh duniya dekhte hain jahan kuch surprising nahi hota. SC mein, ek store globally visible hota hai jis pal execute hota hai — koi "core ke andar" limbo nahi hota.

PICTURE. Charon ops ek time ke arrow par thread kiye hue. Hum bad outcome test karte hain aur ek loop paate hain.

Figure — Memory consistency models

Ab contradiction, symbol by symbol. likhte hain matlab " single timeline par se pehle hota hai."

  • r1 == 0 matlab Core 1 ne y tab padha jab y likha nahi gaya tha: .
  • r2 == 0 matlab Core 2 ne x tab padha jab x likha nahi gaya tha: .
  • Program order force karta hai aur .

Inhe chain karo:

Yahan har symbol ek timeline par ek position hai; chain kehti hai ki strictly apne aap se pehle hai — impossible. Toh SC ke under double-zero outcome forbidden hai. Accha — yeh hamare forecast se match karta hai.


Step 4 — Store buffer ka aana (real hardware kyun alag hai)

KYA. Har core ko ek private store buffer do: ek chhota FIFO queue jo store ko us pal pakad leta hai jab core use issue karta hai, core ko immediately aage badhne deta hai, aur baad mein store ko shared memory mein drain karta hai.

YEH EXIST KYU KARTA HAI. Shared memory tak (cache system ke through, dekho Cache Coherence) likhna slow hota hai. Core ko wait karwaana saikdon cycles waste kar deta. Toh core apni write is local mailbox-in-waiting mein daalta hai aur aage race karta hai — classic out-of-order speed hacking.

PICTURE. Ab har core ke paas core aur memory wall ke beech ek orange FIFO buffer hai. x=1 Core 1 ke buffer mein baitha hai, wall par nahi pahuncha abhi.

Figure — Memory consistency models

Step 5 — Bypass: ek load ek not-yet-visible store ko overtake karta hai

KYA. Ek core trace karo. Core 1 execute karta hai: x=1 uske buffer mein gir jaata hai (wall par nahi). Core 1 immediately run karta hai: y padho. Woh apne buffer mein y dhundta hai — wahan kuch nahi (usne sirf x likha tha) — toh woh y directly wall se padhta hai, jo abhi bhi 0 keh rahi hai. Toh tab complete hota hai jab abhi bhi buffer mein atka hua hai.

YEH CRUCIAL MOVE KYU HAI. Load ab finish ho gaya pehle ki store globally visible hua. Bahar wali duniya ke nazariye se, Core 1 ka load uske store se pehle hua. Yahi exactly woh reordering hai jiska parent note naam rakhta hai:

Har label: S = buffered store ; L = baad wala load ; arrow "" = program order; poori cheez allowed hona TSO ki ek relaxation hai (uska "ek paap").

PICTURE. Ek violet load-arrow orange buffered store ko leap kar ke wall tak pehle pahunchta hai.

Figure — Memory consistency models

Step 6 — Dono cores ek saath karte hain ⇒ double zero

KYA. Exact same trick dono cores par, interleaved, run karo:

  1. x=1 → Core 1 ka buffer (wall abhi bhi x=0).
  2. y=1 → Core 2 ka buffer (wall abhi bhi y=0).
  3. Core 1 wall se y padhta hai → r1 = 0.
  4. Core 2 wall se x padhta hai → r2 = 0.
  5. Baad mein, dono buffers drain hote hain; wall finally x=1, y=1 ban jaati hai — lekin loads pehle ho chuke the.

AB YEH KYU KAAM KARTA HAI. Step 3 mein double-zero ko ek timeline loop chahiye tha aur woh mar gaya. Yahan koi single timeline nahi hai: har store ek private buffer mein rehta hai, doosre core ko invisible, reads ke waqt. Cycle kabhi nahi banta kyunki "" (visible events ka ek global order) mein read-time par buffered stores nahi hote. Paradox dissolve ho jaata hai.

PICTURE. Dono loads ke pal ka snapshot: dono buffers mein 1 hai, dono loads wall se 0 kheench rahe hain.

Figure — Memory consistency models

Step 7 — Degenerate aur edge cases (taaki kuch surprise na kare)

KYA. Har bacha hua outcome aur boundary conditions walk karo.

KYU. Ek contract ko sab inputs cover karne chahiye. Agar hum sirf flashy double-zero dikhate toh teen ordinary outcomes aur do boundary behaviours chhup jaate.

SB test ke chaar possible result-pairs:

r1 r2 Kaise hota hai TSO par allowed?
0 1 Core 1 ne y jaldi padha; Core 2 ne x drain hone ke baad padha ✅ (SC mein bhi)
1 0 Upar wali row ka mirror image ✅ (SC mein bhi)
1 1 Dono buffers kisi bhi load se pehle drain ho gaye ✅ (SC mein bhi)
0 0 Dono loads tab chale jab dono stores buffered the ✅ sirf TSO, ❌ SC

Boundary cases:

  • Buffer instantly drain hota hai (empty buffer): bilkul SC jaisa behave karta hai — aap simply kabhi 0,0 observe nahi karte. Toh SC, TSO ka special case hai jahan stores kabhi late nahi hote.
  • Har core par store aur load ke beech fence insert karo: `MFENCE` buffer ko load run hone se pehle drain karta hai, toh buffered store pehle wall tak pahunchta hai. Step 5 ka bypass ab forbidden hai → 0,0 row disappear ho jaati hai. Yahi acquire/release idea hai jo C++ aur locks use karte hain.
  • Dono sides par same variable (x=1; r=x): load apne khud ke buffer se store-forwarding ke zariye hit karta hai aur 1 padhta hai, kabhi 0 nahi. Coherence, consistency nahi, ek single address govern karta hai — buffer ek value us core se nahi chhupa sakta jo usne likhi hai.

PICTURE. 2×2 outcome grid; 0,0 cell glowing, ek fence padlock ke saath jo use grey kar deta hai.

Figure — Memory consistency models

Ek-picture summary

Upar sab kuch, compressed: SC = ek honest timeline (no double-zero). TSO = private FIFO buffers load ko not-yet-visible store bypass karne dete hain (S→L), toh dono cores 0 padh sakte hain. Ek fence buffer drain karta hai aur SC ko exactly wahan restore karta hai jahan aapko chahiye.

Figure — Memory consistency models
Recall Feynman retelling — poora walkthrough simple words mein

Do bacche, Anna aur Bob, dono ke desk par ek outbox hai aur wall par ek shared bulletin board. Har bacche ke liye akele rule: cheezein top-to-bottom karo. Anna "x=1" likhti hai lekin wall tak jaane ki bajaye apne outbox mein daal deti hai aur immediately wall par "y" jo bhi likha hai padh leti hai — abhi bhi purana 0. Bob mirror karta hai. Toh dono purana 0 padhte hain, aur sirf baad mein unke notes pin hote hain. Kisi ne apna top-to-bottom rule nahi toda, phir bhi wall dekhne wala bahar ka koi insaan dono bacchon ko likhne se pehle padhte dekh sakta hai. Yahi store buffer ka S→L bypass hai. Agar Anna ko sach mein zaroori hai ki uski write pin ho pehle woh padhe, toh woh "FENCE!" chillati hai aur wall ke paas wait karti hai jab tak uski note up nahi ho jaati — slow, lekin ab double-zero kabhi nahi ho sakta. Memory model bas posted class rule hai jo kehta hai ki wall in surprises mein se kaun se dikhane ki permission rakhti hai.

Recall Quick self-check

SC contradiction cycle TSO ke under kyun nahi ban sakta? ::: Kyunki buffered stores load time par global visible-order mein nahi hote, toh chain kabhi close nahi hoti. TSO exactly kaun si single ordering relax karta hai? ::: S→L (ek store ko baad wale load dwara overtake kiya ja sakta hai). Fence yahan physically kya karta hai? ::: Store buffer drain karta hai, store ko globally visible hone par force karta hai following load run hone se pehle.