Coalesced memory access
6.2.8· Hardware › GPU Architecture
Coalesced Memory Access Kya Hai?
Coalesced memory access tab hoti hai jab ek GPU warp ke threads consecutive memory addresses access karte hain jinhe minimum number of memory transactions se serve kiya ja sake. GPUs fixed-size transactions (ek fixed number of bytes ke bursts) mein memory fetch karti hain. Jab ek warp ke threads ka data kam se kam possible transactions mein aa jaye, toh access coalesced hai. Jab requests bahut saari transactions mein scatter ho jaayein, memory efficiency gir jaati hai.
GPUs Kyun Care Karti Hain: Hardware Reality
Memory Transaction Granularity (Architecture-Dependent!)
GPU memory controllers fixed-size transactions mein data fetch karte hain. NVIDIA GPUs par representative values:
| Level | Fermi/Kepler/Pascal | Volta/Turing/Ampere+ |
|---|---|---|
| L1 cache line (fill granularity) | 128 bytes | 128 bytes |
| L2 cache line | 32 bytes (sector) within 128-byte line | 32-byte sectors within 128-byte line |
| Global memory (DRAM) transaction | 128-byte transactions (segmented into 32-byte parts) | 32-byte sectors independently service kar sakta hai |
Key architectural distinction:
- Older GPUs (Fermi/Kepler/Pascal): L1 se ek global load poora 128-byte cache line pull karta hai.
- Newer GPUs (Volta+): memory subsystem sectored hai, isliye yeh 32-byte sectors ko independently service kar sakta hai, partial accesses par kam bandwidth waste hoti hai.
Jab thread 0 address 0x1000 read karta hai, hardware sirf 4 bytes fetch nahi karta — woh poora transaction/sector fetch karta hai jo us address ko contain karta hai (jaise ki ek 32-byte sector 0x1000–0x101F, ya architecture aur cache configuration ke hisaab se ek full 128-byte line).
KYUN? DRAM chips rows aur columns mein organized hoti hain. Ek byte padhne ka cost almost ek poora burst padhne jaisa hi hota hai. Memory controller bursts fetch karne ke liye optimized hai, individual bytes ke liye nahi. Coalescing is hardware reality ko exploit karti hai exact burst size chahe jo bhi ho.
Warp Execution Model
Ek warp ke saare 32 threads same instruction simultaneously execute karte hain (SIMT). Jab woh instruction ek memory load ho, warp scheduler saare 32 addresses collect karta hai aur unhe cover karne ke liye minimum number of memory transactions issue karta hai.
Best case: Saare 32 addresses possible transactions ke smallest set mein aa jaayein → minimum transactions (e.g., 1 × 128-byte line, ya 4 × 32-byte sectors). Worst case: Saare 32 addresses scatter ho jaayein → up to 32 transactions.

Performance Impact Derive Karna
Cost ko quantify karte hain. Neeche di gayi numbers ke liye hum ek model architecture fix karte hain: ek Volta-style sectored memory subsystem jahan global-memory transaction (sector) size bytes hai. (Fermi/Kepler/Pascal par, ko 128-byte line se replace karo aur arithmetic redo karo — result ki shape identical hai.)
Assume karo:
- Warp size: threads
- Memory transaction (sector) size: bytes (256 bits)
- Element size: bytes (float32)
- Memory bandwidth: GB/s
- Memory latency: ns
Coalesced Access (Optimal Pattern)
Threads consecutive floats access karte hain: arr[threadIdx.x] jahan threadIdx.x = 0, 1, 2, ..., 31.
Step 1: Ek transaction mein kitne elements?
Step 2: Warp ke liye kitni transactions chahiye?
4 KYUN? 32-byte sectors ke saath, har transaction 8 consecutive floats fetch karta hai. 32 threads ko 32 floats chahiye, isliye transactions. (128-byte-line architecture par, wohi 128 bytes 1 transaction hain — same data, coarser granularity.)
Step 3: Kitne bytes fetch hue?
Step 4: Fetch karne mein kitna time?
Bandwidth-limited time (sustained transfers ke liye latency ignore karte hue):
Lekin single accesses ke liye memory latency dominant hoti hai: ns (latency) + ns (transfer) ns.
Strided Access (Non-Coalesced)
Threads itne bade stride se access karte hain ki har ek alag transaction mein land kare, jaise arr[threadIdx.x * 8] (stride = 32 bytes = ek sector) ya usse bada:
Thread 0 → address 0x000 (sector 0)
Thread 1 → address 0x0020 (sector 1)
Thread 2 → address 0x0040 (sector 2)
...
Har thread ka address ek alag transaction/sector mein hota hai.
Transactions needed: 32 (ek per thread, har ek alag 32-byte sector mein).
Bytes fetched: bytes (lekin actually sirf bytes use hote hain).
Coalescing se Speedup:
KYUN? Non-coalesced access 32 separate memory transactions force karta hai, har ek ke saath full latency overhead. Tum zaroorat se 8× zyada data fetch karte ho aur 32× zyada latency cost pay karte ho.
Access Patterns: Derivation ke Saath Examples
Example 1: Sequential Access (Perfect Coalescing)
__global__ void sequential(float *data) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
float val = data[idx]; // Thread i reads data[i]
}Address analysis:
- Thread 0:
data[0]→0x000 - Thread 1:
data[1]→0x0004(4 bytes baad) - Thread 31:
data[31]→0x007C(thread 0 se 124 bytes)
Saare 32 addresses exactly 128 contiguous bytes span karte hain: .
Transactions (architecture-dependent, lekin hamesha minimum possible):
- 128-byte-line architecture (Fermi/Kepler/Pascal): yeh 128 bytes ek aligned cache line hain → 1 transaction.
- 32-byte-sector architecture (Volta+): 128 bytes = chaar aligned sectors → 4 transactions.
Dono cases mein, 128 useful bytes padhne ke liye yeh minimum hai, aur fetched bytes ka 100% use hota hai. Iska matlab yahi hai "coalesced" — ek fixed transaction count nahi.
KYUN kaam karta hai: Memory addresses stride 4 ke saath monotonically increase karte hain (float ka size). Controller saare 32 requests ko minimum transactions aur zero wasted bytes se cover karta hai.
Example 2: Strided Access (Worst Case)
__global__ void strided(float *data) {
int idx = threadIdx.x * 1024; // Stride = 1024 floats = 4096 bytes
float val = data[idx];
}Address analysis:
- Thread 0:
0x0000 - Thread 1:
0x1000(4096 bytes door) - Har thread ka address ek alag transaction/cache line mein hai.
Transactions: 32 (ek per thread), kisi bhi architecture par, kyunki koi bhi do threads ek transaction share nahi karte.
Bytes fetched (32-byte-sector arch): bytes. Bytes used: bytes. Waste: bytes (sectored GPU par 87.5% waste; 128-byte-line GPU par toh aur bhi bura — 96.9% — kyunki use per thread ek full line pull karni padti hai).
KYUN fail hota hai: Stride transaction size se bada hai. Koi bhi do threads ek transaction share nahi karte, isliye har thread ek alag transaction trigger karta hai.
Example 3: Structure of Arrays vs. Array of Structures
Array of Structures (AoS) – Non-coalesced:
struct Particle {
float x, y, z; // 12 bytes
float vx, vy, vz; // 12 bytes
};
__global__ void aos(Particle *particles) {
int idx = threadIdx.x;
float x = particles[idx].x; // Access x-coordinate
}Address analysis (struct = 24 bytes):
- Thread 0:
particles[0].x→0x0000 - Thread 1:
particles[1].x→0x0018(24 bytes baad) - Thread 31:
particles[31].x→0x02E8(744 bytes)
32 accessed x-values bytes ke address space mein spread hain, lekin har 24 bytes mein sirf 4 useful bytes read hoti hain.
Transactions (32-byte-sector arch): touched bytes sectors span karti hain, isliye ~24 transactions, jinmein zyada bytes waste hain.
Structure of Arrays (SoA) – Coalesced:
struct Particles {
float *x; // All x-coordinates together
float *y, *z;
float *vx, *vy, *vz;
};
__global__ void soa(Particles p) {
int idx = threadIdx.x;
float x = p.x[idx]; // Consecutive access
}Address analysis: Example 1 (sequential) jaisa hi. Thread , p.x[i] read karta hai, stride = 4 bytes.
Transactions: 4 (32-byte sectors) ya 1 (128-byte line) — minimum, 100% efficiency.
KYUN SoA jeet ta hai: Fields ko alag karne se threads homogeneous data ko sequence mein access kar paate hain, aur har thread ke zaroorat ke data ke beech koi wasted bytes nahi hote.
Common Mistakes aur Steel-Manning
Active Recall Flashcards
#flashcards/hardware
GPU programming mein coalesced memory access kya hai?
GPU memory controller individual bytes ki jagah bursts mein data kyun fetch karta hai?
Kya GPU transaction/cache-line sizes saare NVIDIA GPUs par universal hain?
Agar 32 threads itne bade stride se floats access karein ki har ek alag transaction mein land kare, toh kitni transactions chahiye hongi?
GPU access patterns ke liye memory efficiency formula kya hai, aur yeh architecture-independent kyun hai?
GPUs par Structure of Arrays (SoA) typically Array of Structures (AoS) se behtar kyun perform karta hai?
1-element offset (jaise data[threadIdx.x + 1]) coalescing ko kaise affect karta hai?
Connections
- 6.2.01-GPU-execution-model – Warps lockstep mein execute karte hain, isliye saare 32 threads ke memory requests simultaneously collect hote hain. Coalescing SIMT model par depend karta hai.
- 6.2.04-Shared-memory-and-synchronization – Locality shared memory par bank conflicts ke zariye apply hoti hai. Strided shared memory access serialization cause karta hai.
- 6.2.09-Memory-hierarchy – Transaction aur cache-line sizes (architecture-dependent) coalescing granularity determine karti hain. L1 (128 bytes) aur L2 (128-byte lines ke andar 32-byte sectors) transaction counts affect karte hain.
- 6.3.02-Roofline-model – Coalescing directly achieved memory bandwidth ko impact karta hai. Non-coalesced code hardware roofline se bahut neeche operate karta hai.
- 5.1.05-Cache-coherence-protocols – GPUs traditional snooping coherence use nahi karte, lekin L1/L2 caches abhi bhi spatial locality exploit karte hain, jo coalescing maximize karta hai.
Recall Ek 12-Saal-Ke Bachche Ko Explain Karo
Socho tum aur tumhare 31 dost ek line mein library mein khade ho, aur tumhe sab ko books chahiye. Librarian ek badi cart le ja sakta hai jo ek baar mein kaafi books carry kar sake. Agar tum sab ek hi shelf par aas-paas rakhi books maango (book 1, book 2, book 3, ...), toh librarian cart ko chand quick grabs mein bhar leta hai aur sab ko unki book de deta hai. Aasaan!
Lekin agar tum mein se har koi library mein bilkul alag shelf se book maange (shelf A se book 1, shelf Z se book 2000, shelf Q se book 5000, ...), toh librarian ko har insaan ke liye alag trip karni padegi — 32 trips tak. Yeh bahut zyada time leta hai, chahe tum phir bhi ek hi book le rahe ho.
Coalesced memory access woh hai jab tumhare GPU ka "librarian" (memory controller) tumhare 32 threads ka saara zaroori data kam se kam trips mein fetch kar sake kyunki tumne memory mein ek doosre ke paas ki cheezein maangi theen. Jab tumhara code saara jagah scattered data maangta hai, GPU ko bahut saari trips karni padti hain, aur tumhara program slow ho jaata hai. Trick yeh hai ki apna data organize karo aur use order mein access karo, taaki GPU sabkuch kam se kam trips mein grab kar sake!
Generated: 2026-07-01 | Context: GPU memory performance optimization