6.1.10 · D5 · HinglishParallelism & Multicore

Question bankFalse sharing problem

1,840 words8 min read↑ Read in English

6.1.10 · D5 · Hardware › Parallelism & Multicore › False sharing problem

Traps se pehle, ek anchor picture — taaki neeche har claim pe point karne ke liye kuch ho:

Figure — False sharing problem

Dono variables x aur y alag bytes hain lekin same 64-byte line ke andar baithe hain. Hardware coherence unit poori line hai — woh us byte boundary ko nahi dekh sakta jis par tumhara dhyan hai. Ye image dimag mein rakho; neeche har trap isi ka ek variation hai.


True or false — justify karo

True or false: False sharing ek correctness bug hai jo galat answers de sakta hai.
False — ye sirf ek performance bug hai. Har read aur write sahi value hi return karta hai; program bas slow hota hai kyunki line caches ke beech ping-pong karti rehti hai.
True or false: Agar do variables ek hi cache line mein hain lekin sirf ek core kabhi unhe write karta hai, to false sharing phir bhi hoti hai.
False — false sharing ke liye ek writer ka doosre accessor se compete karna zaroori hai. Ek akela writer apne cache mein line ko Modified rakhta hai bina kisi invalidation traffic ke.
True or false: Do cores jo sirf same cache line ko read karte hain unhe false sharing hoti hai.
False — MESI ka Shared state kai caches ko ek saath read-only copy rakhne deta hai. Invalidations tab tak fire nahi hote jab tak koi write na kare.
True or false: Har counter par std::atomic use karne se false sharing khatam ho jaati hai.
False — atomics torn/lost updates ki guarantee dete hain lekin atomic write ko phir bhi line Modified state mein chahiye, isliye wo doosre core ki copy ko bilkul waise hi invalidate karta hai jaise ek plain write.
True or false: False sharing do bilkul unrelated global variables ke beech ho sakti hai jinhe tumne kabhi paas rakhne ka iraada nahi kiya tha.
True — linker/allocator independent globals ko same line ke adjacent bytes mein rakh sakta hai; logical independence physical separation nahi deta.
True or false: Cache line ko bada karne se false sharing kam hogi.
False — badi line mein zyada independent variables pack hote hain, isliye false sharing zyada likely ho jaati hai, kam nahi.
True or false: False sharing tab aur buri hoti hai jab zyada cores shared line pe write karte hain.
True — har extra writer ek aur party add karta hai jise invalidate karna padta hai, isliye ping-pong mein zyada caches involve hote hain aur coherence traffic scale up hota hai, jisse Multicore scaling hurt hoti hai.
True or false: Ek struct ko 64 bytes tak pad karne se hamesha exactly 60 bytes per element waste hote hain.
False — waste bytes hai; ye payload size pe depend karta hai, aur agar payload already ek line bharta hai to waste zero ho sakta hai.
True or false: Single-core machine par, false sharing phir bhi program ko slow karta hai.
False — ek core ke saath sirf ek cache hai aur invalidate karne ke liye koi doosri copy nahi, isliye coherence ping-pong jo false sharing define karta hai wo arise hi nahi ho sakta.

Error dhundho

"Maine har counter ko 8 bytes align kiya, isliye har ek ko apni cache line milti hai." — kya galat hai?
8-byte alignment abhi bhi aath variables ko ek 64-byte line mein pack karta hai. Tumhe line size (64 bytes) ke according alignment chahiye, na ki word size ke. Dekho Cache line size and alignment.
"Mere struct ke fields private hain aur har thread sirf apna field touch karta hai, isliye koi sharing nahi hai." — kya galat hai?
Language-level privacy hardware ke liye invisible hai. Coherence protocol physical addresses par kaam karta hai; agar private fields ek line share karte hain, to wo false sharing karte hain chahe access modifiers kuch bhi ho.
"Main false sharing theek karne ke liye har counter ke around lock lagaunga." — kya galat hai?
Lock access serialize karta hai lekin bytes kahan hain usse kuch nahi karta. Lock khud false-share kar sakta hai, aur sahi locking bhi same line bounce karta rehta hai — tumne contention add kiya, separation nahi.
"False sharing sirf arrays ko affect karti hai, isliye meri scalar variables safe hain." — kya galat hai?
Koi bhi do hot variables jo same line mein land karti hain false-share karti hain, chahe wo array se aayi hon, do struct fields se, ya do separate globals se jo allocator ne adjacent rakh diye.
"Maine apne int value ke baad char padding[64] add kiya, to ab ye ek full line hai." — kya galat hai?
int plus 64 padding bytes = 68 bytes — jo ek line se bada hai, isliye do elements ek boundary par straddle kar sakte hain aur phir bhi share kar sakte hain. Tum chahte ho ki total 64 ke barabar (ya align) ho, jaise char padding[60].
"Main value core 0 par read karta hoon aur sirf core 1 par write karta hoon, isliye core 0 par koi invalidation nahi hoti." — kya galat hai?
Core 1 ka write line ko core 1 mein Modified force karta hai, jo core 0 ki read copy ko invalidate karta hai. Core 0 ka agla read tab miss karta hai aur re-fetch karna padta hai — yahi exactly false-sharing ka cost hai.
"False sharing avoid karne ke liye maine do variables ko 32 bytes alag kar diya." — kya galat hai?
32 bytes 64-byte line se kam hai, isliye wo abhi bhi same line mein ho sakte hain. Separation kam se kam ek poori line ki honi chahiye aur base addresses alag lines mein land karni chahiye.

Why questions

CPU individual-byte level par sharing track kyun nahi kar sakta taaki ye avoid ho?
Byte-level coherence tags ke liye enormous per-byte state aur traffic chahiye; hardware us tradeoff ki jagah poori cache lines track karta hai, jo normally efficient hai lekin sub-line independence ke liye andha hai.
Read-modify-write (jaise counter++) false sharing ke liye worst pattern kyun hai?
Ise complete karne ke liye line exclusive/Modified state mein chahiye, isliye har increment ko line own karni padti hai — jo guaranteed karta hai ki har doosra core jo isko touch kare, invalidate ho. Dekho Atomic operations.
False sharing kyun hurt karti hai jabki "koi real data dependency" nahi hai?
Dependency physical hai, logical nahi — shared 64-byte transfer unit variables ko couple karta hai. Hardware line par coherence enforce karta hai, isliye independent logic phir bhi coherent-transfer cost chukati hai.
Padding "space ke badle time" kyun trade karta hai?
Tum extra memory (dead padding bytes) kharach karte ho taaki har hot variable apni line own kare; payoff ye hai ki ~100–200 coherence cycles per write se ~1–2 local cycles par aa jaate ho.
std::hardware_destructive_interference_size hard-coding 64 se better kyun hai?
Ye compiler ko architecture ki sahi line size pick karne deta hai (kuch CPUs alag hote hain, aur prefetchers pairs of lines fetch kar sakte hain), tumhari padding ko portable rakhta hai ek x86 assumption se bandhe rehne ki jagah.
"Harmless" refactor ke baad false sharing quietly kyun appear ho sakti hai jo struct fields reorder karta hai?
Reordering change karta hai ki kaunse fields kaunsi line mein land karte hain. Ek field jo do cores hammer karte hain wo lonely line se shared line mein move ho sakta hai, isliye identical logic suddenly ping-pong karne lagta hai. Isisliye Memory allocators aur layout choices matter karte hain.
False sharing NUMA architectures ke saath kyun buri tarah interact karti hai?
Invalidated line remote memory node mein ho sakti hai, isliye isko re-fetch karna interconnect cross karta hai — ek local cache miss ko ek kaafi expensive cross-node round trip mein badal deta hai.

Edge cases

Agar ek variable sirf ek core write karta hai lekin kaafi log read karte hain, to line kis state mein settle hoti hai aur kya false sharing hoti hai?
Ye readers ke liye Shared state mein settle hoti hai jab tak writer nahi aata; ek akela writer periodically sab readers ko invalidate karta hai, isliye haan, real coherence traffic hoti hai — ye ek milder lekin genuine false-sharing case hai.
Kya hota hai agar do false-sharing variables actually kabhi same time pe access nahi ki jaati (jaise phase-separated)?
Agar accesses time mein kabhi overlap nahi karte, to line cleanly hand off hoti hai bina contention ke; false sharing tab hi kaatti hai jab cores ke beech line pe writes interleave hoti hain.
Kya false sharing hoti hai agar dono variables ek line mein hain jo currently dono caches mein Invalid state mein hai (cold start)?
Pehle touch par invalidate karne ke liye koi doosri copy nahi hai, isliye abhi tak koi false-sharing penalty nahi; ping-pong tab shuru hoti hai jab dono cores ne line populate karke write karna shuru kar diya ho.
False sharing ke liye kam se kam kitne cores aur writers chahiye?
Kam se kam do cores, aur kam se kam do accessors of the same line jahan ek writer ho — har core par ek, har ek shared line ke alag byte ko hit karta hua.
Agar sizeof(payload) already cache line size ke barabar hai, to kitna padding chahiye?
Kuch nahi — payload akela line bharta hai, isliye agla element naturally naye line par shuru hota hai, jo free mein deta hai.
Kis array size par counter[0] aur counter[7] (4-byte ints, 64-byte line) ke beech false sharing naturally khatam ho jaati hai?
counter[0]..counter[15] sab ek line mein fit hote hain, isliye indices 0 aur 7 use share karte hain; ye tab hi alag hote hain jab elements ≥16 apart hoon, yaani index 16 par agली line mein jaayein.
Recall Jaane se pehle quick self-check

False sharing ek ___ bug hai (correctness nahi), trigger hoti hai jab ___ cores same ___ line ke alag bytes mein write karte hain, fix hoti hai har hot datum ko apni line par ___ karke. ::: performance; two or more; same cache; padding/aligning.