Bank conflicts in shared memory
6.2.9· Hardware › GPU Architecture
Ye kyun matter karta hai: Shared memory fast honi chahiye (~100× global memory se faster). Bank conflicts is advantage ko barbad kar dete hain parallelism ko serialize karke.
How shared memory banks work
First principles se derivation:
- 4 se divide kyun? Har bank 4 bytes wide hota hai (NVIDIA hardware par fixed bank width). Ek byte address ko word index mein convert karna padta hai. Address 0-3 → word 0, address 4-7 → word 1, etc.
- Mod 32 kyun? 32 banks ke saath, hum words ko round-robin fashion mein distribute karte hain. Word 0 → bank 0, word 1 → bank 1, .., word 31 → bank 31, word 32 → bank 0 phir se.
- Result: Words banks mein striped hote hain. Consecutive 32-bit words consecutive banks mein rehte hain.

Types of access patterns
Ye kyun kaam karta hai:
- Thread 0 reads
shared[0]→ word 0 → bank 0 - Thread 1 reads
shared[1]→ word 1 → bank 1 - ...
- Thread 31 reads
shared[31]→ word 31 → bank 31
Saare 32 threads alag-alag banks hit karte hain → 1 cycle access, perfect parallelism.
Analysis:
- Thread 0:
shared[0]→ bank 0 - Thread 1:
shared[2]→ bank 2 - Thread 2:
shared[4]→ bank 4 - ...
- Thread 16:
shared[32]→ word 32 → bank ← thread 0 se conflict! - Thread 17:
shared[34]→ bank 2 ← thread 1 se conflict!
Result: 16 pairs of threads collide (2-way conflicts). Access 2 cycles leta hai 1 ki jagah.
Ye step kyun? Stride-2 ke saath, har 16 threads baad hum bank 0 par wapas aa jaate hain. 16 positions ke antar par wale threads same bank request karte hain.
- Thread 0:
shared[0]→ bank 0 - Thread 1:
shared[32]→ word 32 → bank 0 - Thread 2:
shared[64]→ word 64 → bank 0 - Saare 32 threads bank 0 hit karte hain!
Access time: 32 cycles (fully serialized). Shared memory ab registers se bhi slow hai.
The mathematical pattern
Derivation:
- Thread word index access karta hai.
- Thread ke liye bank: .
- Do threads aur conflict karte hain agar .
- Yeh simplify hota hai mein.
- Sabse chhota jo yeh satisfy kare woh hai .
- Toh har threads par, banks repeat hote hain, matlab threads har bank par collide karte hain.
Examples:
- Stride 1: → koi conflict nahi
- Stride 2: → 2-way conflict
- Stride 3: → koi conflict nahi (odd strides safe hain!)
- Stride 16: → 16-way conflict
- Stride 32: → 32-way conflict
Common mistake: structure-of-arrays vs array-of-structures
Pehli nazar mein galat kyun lagta hai: "Threads 12 bytes apart hain, toh surely banks par collide karenge."
Sach mein kya hai: Chalte hain actually .x access ke liye banks compute karte hain.
- Adjacent
.xfields ke beech word stride 3 words hai (12 bytes / 4). - Thread word access karta hai, bank par land karta hai.
- Kyunki , map 32 banks ki ek permutation hai.
- Thread 0→bank 0, T1→bank 3, T2→bank 6, ..., T10→bank 30, T11→bank 33 mod 32 = bank 1, ...
Toh ek warp ka .x (ya .y, ya .z) read actually CONFLICT-FREE hai, kyunki 3 aur 32 coprime hain. Yeh intuition ki "non-unit stride = conflict" galat hai; sirf woh strides jo 32 ke saath koi factor share karein (yaani even strides / powers of 2) conflicts cause karte hain.
Jab AoS sach mein problem karti hai: Conflicts tab aate hain jab struct size 32 ke saath koi factor share kare — jaise 4 floats ka struct (16 bytes = 4 words). Tab stride = 4, → har field par 4-way conflict. AoS ki real danger yahi hai: aap stride control nahi karte, aur ek "achhi" power-of-two struct size silently conflicts create kar deti hai.
Robust fix: Structure-of-arrays
__shared__ float x[32], y[32], z[32];
float px = x[threadIdx.x]; // Stride-1, guaranteed conflict-free
float py = y[threadIdx.x];
float pz = z[threadIdx.x];SoA har field access ko stride-1 banata hai, toh aap kabhi is par depend nahi karte ki struct size 32 ke saath coprime ho.
Padding to avoid conflicts
Case A — same row, alag columns (yeh conflict-free hai):
float value = matrix[row][tid]; // fixed row, tid = column- Thread word access karta hai. Jab vary karta hai, stride 1 word hai.
- Banks: (kyunki ). Saare alag → koi conflict nahi.
Case B — same column, alag rows (yeh wala bura hai):
float value = matrix[tid][col]; // tid = row, fixed column- Thread word access karta hai. Stride 32 words hai.
- Banks: , har thread ke liye same → 32-way conflict!
Yeh column-walk pattern exactly wahi hai jo matrix transpose mein hota hai, isliye yeh bahut important hai.
Fix: inner dimension ko 33 tak pad karo
__shared__ float matrix[32][33]; // ek extra padding column
float value = matrix[tid][col]; // column access- Ab element word par hai.
- Thread (row , fixed column) word access karta hai.
- Bank index (extra /4 nahi — hum already word units mein hain): kyunki .
- Jab 0..31 tak run karta hai, saare 32 distinct values leta hai → conflict-free!
Yeh step kyun? 33 tak padding karne se row stride ho jata hai, toh consecutive rows exactly ek bank shift hoti hain same bank par land karne ki jagah. Yahi poora trick hai.
Recall Ek 12-saal ke bacche ko explain karo
Socho tumhare school mein 32 cubbyholes hain jahan students apne lunch boxes rakhte hain. Rule yeh hai: student 1 cubby 1 use karta hai, student 2 cubby 2, aur student 32 tak cubby 32. Phir repeat hota hai: student 33 phir cubby 1 use karta hai.
Ab, 32 dost (ek "warp") ek saath apna lunch lene ki koshish karte hain. Agar unhone cubbies 1, 2, 3, .., 32 mein lunch rakha tha, toh sabko ek saath mil jaata hai — wait nahi karni! Yahi conflict-free hai.
Lekin kya agar unhone sab ne cubby 1 mein lunch rakha? Ab teacher ko ek ek karke dena padega — super slow! Yahi 32-way bank conflict hai.
Bank conflicts tab hote hain jab multiple threads (students) ek saath same bank (cubby) se data chahein. GPU ko unhe ek ek karke serve karna padta hai sab ek saath ki jagah. Trick yeh hai ki apna data aise organize karo ki har thread alag bank use kare — jaise ensure karo ki har student ka cubby number alag ho. Har row mein ek "khali spare cubby" add karna (padding to 33) sabko ek shift kar deta hai taaki woh same cubby par clash karna band kar dein.
Connections
- Shared memory architecture—woh physical design jo banks ko enable karta hai
- Memory coalescing—global memory ke liye similar parallelism concept
- Occupancy—bank conflicts effective occupancy reduce karte hain warps stall karke
- Matrix transpose—classic example jahan padding conflicts fix karti hai
- Warp divergence—GPU execution mein ek aur serialization bottleneck
#flashcards/hardware
Shared memory banks kya hain aur ye kyun exist karte hain? :: Banks shared memory ke parallel sub-units hain (typically 32) jo multiple threads ko alag-alag addresses simultaneously access karne dete hain. Ye high-bandwidth parallel access enable karne ke liye exist karte hain — har bank ek cycle mein ek request serve kar sakta hai.
Bank conflict kya hota hai? :: Jab ek warp ke multiple threads alag-alag addresses access karein jo same bank pe map hote hain, toh parallel access ki jagah serialized access force hoti hai. Yeh latency ko conflict degree se multiply kar deta hai.
4-byte words ke liye bank index kaise calculate hota hai?
Stride-2 access ke liye conflict degree kya hai? :: 2-way conflict. gcd(2, 32) = 2, toh har do threads same bank par collide karte hain, access time double ho jata hai.