Suppose a memory operation takes L=400 cycles. An SM can issue 1 warp-instruction per cycle (for a single scheduler; modern SMs have 4 schedulers, but let's start simple).
Goal: Keep the pipeline full—issue 1 instruction every cycle.
Problem: A warp that issues a memory load must wait L cycles before its result is ready.
Solution: Have Lother warp-instructions ready to issue during that wait.
Thus:
Warps needed≥Instructions per Warp per CycleL
If each warp issues 1 instruction/cycle when scheduled:
Warps≥L
For L=400 cycles → need 400 warp-instructions in flight to fully hide latency with 1 scheduler. Modern SMs with 4 schedulers and pipelined execution supply much of this concurrency per cycle. In practice, 16-32 active warps suffice for most kernels due to:
Multiple instructions in flight per warp (ILP)
Mix of compute and memory ops
4 schedulers issuing from different warps in consecutive cycles (SM-wide MLP)
WHY 32 threads per warp?
Historical: SIMD width balances hardware complexity vs. paralelism. 32 lanes means 32-wide vector ALUs, which fit transistor budgets and memory coalescing patterns (cache lines are 128B = 32× 4-byte floats).
Imagine you're doing homework. Each question takes you 2 minutes to read, 10 seconds to solve. If you only have 1 question, you sit idle for 2 minutes waiting for it. Boring!
But if you have 12 questions, you read Question 1, then while the book "loads" Question 2, you solve Question 1. You never wait—you're always working on something. (Reading Question 1 still takes the full 2 minutes—you just fill that time with other work, you don't make the book load faster.)
A GPU is like having 1000 questions and 1000 brains. Each brain (thread) grabs a question. While one brain waits for the "book" (memory) to load, 999 others are solving. By the time you cycle back, the first brain's book is ready.
Occupancy is: "How many of your brains are busy?" If 500 out of 1000 brains have questions, occupancy is 50%. The more busy brains, the less waiting.
The ratio of active warps to maximum possible warps per SM, usually expressed as a percentage (e.g., 32/64 = 50%).
Why does high occupancy hide latency?
With many active warps, the warp scheduler can always find a ready warp to execute while others wait for memory or ALU results, eliminating stalls.
What are the three main factors limiting occupancy?
(1) Registers per thread, (2) Shared memory per block, (3) Maximum blocks per SM. Occupancy is the minimum of these constraints.
Does adding warps reduce the latency of a single memory load?
No. Concurrency (Little's Law) lets you overlap many loads so the SM never idles, but the intrinsic ~400-cycle latency of each load is unchanged.
Derive the latency hiding requirement from Little's Law
To hide latency L cycles at throughput T ops/cycle, need L×T operations in flight. For 400-cycle memory latency and 1 warp-instruction/cycle, need ~400 warp-instructions outstanding (but ILP + SM-wide MLP + 4 schedulers reduce distinct warps to 16-32).
Why is 100% occupancy not always optimal?
Beyond ~50%, gains plateau. High occupancy can increase cache pressure and register spills, hurting performance. The goal is zero stalls, not maximum threads.
What is the A100's maximum occupancy in warps per SM?
64 warps/SM (2048 threads, since each warp = 32 threads).
If a kernel uses 80 registers/thread on an A100 (65,536 regs/SM), what's the occupancy?
How many outstanding memory requests does a single warp sustain?
One memory instruction at a time (which may split into a few transactions if uncoalesced). Concurrency comes SM-wide across many warps, not from one warp issuing 32 independent requests.
Do global stores add their full latency to the critical path?
No. Global stores are buffered and retire asynchronously (drain in the background), so you normally don't add store latency to critical-path memory time.
When does low occupancy NOT hurt performance?
When the kernel is compute-bound with high instruction-level parallelism (ILP), or when achieved throughput already saturates the hardware despite fewer active warps.
Dekho, GPU ka core magic ye hai ki wo slow memory ka wait nahi karta. Jab ek warp (32 threads ka group) memory se data lane ke liye ruka hota hai—jo ki 400-800 cycles le sakta hai—tab GPU dusre ready warps ko chalata rehta hai. Isko bolte hain latency hiding. Aur occupancy simply ye batata hai ki tum apne SM (Streaming Multiprocessor) ki capacity ka kitna hissa use kar rahe ho—yaani active warps divided by maximum possible warps. Restaurant kitchen wali example yaad rakho: agar tumhare paas 100 orders hain to har chef busy rehta hai, koi idle nahi khada, aur ingredients ka wait ho bhi to kaam ruकता nahi.
Ab ye matter kyun karta hai? Kyunki context switching GPU mein bilkul free hai—har warp ke registers on-chip padhe rehte hain, to warp badalne mein zero cycles lagte hain. Warp scheduler har cycle ek aisa warp uthata hai jo ready ho (jiska data aa gaya ho ya jo waiting nahi hai). Isliye agar tumhare paas kaafi warps hain, to SM kabhi stall nahi hoti aur pipeline hamesha bhari rehti hai. Little's Law bhi yahi kehta hai: latency L ko hide karne ke liye tumhe L× throughput jitni concurrency chahiye. Practically 16-32 active warps zyadatar kernels ke liye enough hote hain, kyunki multiple instructions per warp (ILP) aur 4 schedulers milkar concurrency provide kar dete hain.
Lekin ek important cheez samajhna—occupancy tumhare registers per thread, shared memory per block, aur blocks per SM jaisi resources se limit hoti hai. Agar tumhara kernel bahut zyada registers use karta hai, to kam warps fit honge aur occupancy gir jayegi. Isliye final occupancy in saare constraints ka minimum hoti hai. Yaad rakho, zyada concurrency single operation ki latency ko chhota nahi karti—wo bas overlap karne deti hai taaki SM idle na baithe. Ye samajhna zaroori hai kyunki jab tum performance tune karoge, to tumhe balance karna padega ki registers aur shared memory kitna use karein taaki enough warps chalein aur latency effectively hide ho sake.