Exercises — Streaming multiprocessors (SM)
6.2.2 · D4· Hardware › GPU Architecture › Streaming multiprocessors (SM)
Yeh page Streaming Multiprocessors (SM) ke liye ek self-test ladder hai. Har problem saaf-saaf statement karta hai, phir ek collapsible callout mein poora worked solution chhupata hai — pehle khud try karo, phir reveal karo. Levels recognising (SM ke parts ko pehchaanna) se lekar synthesising (scratch se occupancy strategy banana) tak chadhte hain.
Yahan har number machine-checked hai (verify block dekho). Shuru karne se pehle, ek shared vocabulary reminder — bilkul zero se build kiya gaya hai taaki koi bhi symbol bina samjhe naa aaye.

Upar ki picture ko ek nesting doll ki tarah padho: 32 threads milke ek warp banate hain (blue lane), kaafi warps milke ek block banate hain (outlined box), aur SM kaafi blocks ek saath hold karta hai. Har exercise bas itna hi count karna hai ki in dolls mein se kitni kisi limit ke under fit hoti hain.
Level 1 — Recognition
L1.1 — Warps in a block
Problem. Ek block mein threads hain. Yeh kitne warps hain?
Recall Solution
Ek warp hamesha exactly threads hota hai (yeh koi aisi setting nahi jise tum change kar sako). Toh hum divide karte hain: Hamne kya kiya: threads ko hardware ke fixed 32-wide bundles mein group kiya. Kyun: warp scheduler kabhi individual threads nahi dekhta — yeh hamesha sirf poore warps ko issue karta hai, isliye warps scheduling ki asli unit hain.
L1.2 — Memory tiers ko speed ke hisaab se naam do
Problem. Inhe fastest se slowest access tak order mein rakho: L2 cache, registers, shared memory, global DRAM.
Recall Solution
Parent note ki SM latency ladder use karke: Yeh order kyun hai: har step data ko CUDA cores se physically door le jaata hai. Registers core ke andar hi hote hain; shared memory on-chip SRAM hai jisme koi tag lookup nahi; L2 poore chip pe shared hai; DRAM bilkul off-chip hai. Jitna door = utne zyada cycles. Dekho GPU-memory-hierarchy.
L1.3 — sqrt kaunsi unit handle karta hai?
Problem. Tumhara kernel sqrtf(x) call karta hai. Kaunsa SM component ise handle karta hai: ek CUDA core, ek SFU, ya ek Load/Store unit?
Recall Solution
Special Function Unit (SFU). CUDA cores plain integer/float add aur multiply karte hain; Load/Store units memory move karte hain; SFUs dedicated hardware hain transcendentals ke liye (sin, cos, exp, sqrt). Yeh kyun exist karta hai: yeh functions basic arithmetic se emulate karne par 20–100 cycles lagte hain, lekin SFU par sirf ~1–2 cycles.
Level 2 — Application
L2.1 — Register-limited block count
Problem. Ek kernel registers per thread use karta hai. SM mein registers hain. Block size threads hai. Registers se limited, ek SM par kitne whole blocks fit hote hain?
Recall Solution
Step 1 — registers per block. Har thread ko apni copy chahiye: Step 2 — kitne fit hote hain. SM ki supply ko divide karo, phir floor karo (aadha block resident nahi ho sakta): Floor kyun: ek block SM par ya toh poora hai ya nahi. Agar sirf aadhe block ke liye registers bache hain, toh woh block wait karta hai. Dekho Occupancy-optimization.
L2.2 — Us block count se Occupancy
Problem. L2.1 se jaari: threads ke resident blocks ke saath, aur SM par maximum warps ke saath, occupancy kya hai?
Recall Solution
Resident warps: warps. Occupancy: Iska matlab: scheduler ke sirf ek quarter warp slots mein kaam hai, isliye latency-hiding kamzor hai — L3 dekho.
L2.3 — Register file kitne threads hold kar sakta hai
Problem. Ek kernel registers wale SM par registers per thread use karta hai. Agar registers sirf ek hi limit hote, toh kitne threads resident ho sakte hain?
Recall Solution
Lekin doosra cap bhi dekho: agar SM mein zyada se zyada warps bhi allowed hain, toh yeh threads hain. Yahan , isliye registers binding limit hain. Rule: actual occupancy us resource se set hoti hai jo pehle khatam hoti hai.
Level 3 — Analysis
L3.1 — Ek stall chhupane ke liye kitne warps chahiye?
Problem. Ek global-memory load ek warp ko cycles ke liye stall karta hai. Ek single scheduler instruction per cycle issue karta hai. Us stall ko poori tarah chhupane ke liye roughly kitne independent in-flight warps chahiye? Kya resident warps (L2.1 se) kaafi hain?
Recall Solution
Model: jab stalled warp wait karta hai, scheduler ko cycles tak har cycle mein ek alag ready warp issue karna hoga. Ek warp se ek instruction, phir woh phir stall kyun ho jaata hai: memory-bound kernel mein zyaatar warps ko aage jo karna hota hai woh khud ek aur dependent global load (ya aisi op jo in-flight value consume karegi) hota hai. Toh scheduler kisi warp ko ek instruction issue karne ke baad, woh warp turant apne long-latency access par phir wait karne lagta hai. Isliye yeh cover ke sirf roughly ek useful cycle contribute karta hai phir drop out ho jaata hai. Isliye humein ek warp ko baar baar use karne ki jagah bahut saare alag-alag warps chahiye: Kya 16 warps kaafi hain? Nahi — warps sirf -cycle hole ke cycles cover karte hain per scheduler pass. Baaki cycles scheduler idle baitha rehta hai. Lesson: kam occupancy directly latency-hiding ko bhookha rakhti hai. Yahi wajah hai ki parent note "resident warps maximize karo" par itna zor deta hai.

Bar picture ise visceral bana deti hai: tall red bar -cycle stall hai; warps ka short chalk-blue stack barely ise kuch dent karta hai.
L3.2 — Occupancy speed ke saath linear nahi hai
Problem. Tum occupancy ( warps) se ( warps) tak badhate ho. Kya tumhara compute-bound kernel — jo rarely global memory touch karta hai — faster hoga? Explain karo.
Recall Solution
Nahi. Occupancy sirf latency hide karne mein help karti hai. Ek compute-bound kernel already CUDA cores ko busy rakhta hai; uski bottleneck arithmetic throughput hai, memory ka wait karna nahi. Extra warps sirf same busy ALUs ke liye queue karte hain. Kya badalta hai vs. kya nahi badhta: ek memory-bound kernel ke liye, warps jaana roughly double karta hai jo latency tum chhupa sakte ho aur noticeable help kar sakta hai. Ek compute-bound ke liye, tum near-zero improvement dekh sakte ho — agar extra warps ke liye register cut ki zaroorat padi toh tum speed bhi kho sakte ho, kyunki spills memory mein jaayenge. Analytical point: occupancy ek ceiling raiser for latency hiding hai, throughput multiplier nahi.
L3.3 — Divergence cost
Problem. Ek -thread warp mein, threads – branch A lete hain aur threads – branch B lete hain, har branch instructions ki hai. Warp kitne instruction-issues karta hai, ek non-diverging warp of instructions ke comparison mein?
Recall Solution
SIMT ke under, ek warp saare lanes ke liye ek instruction issue karta hai. Jab lanes split hote hain, hardware dono paths ko sequence mein run karta hai, har baar inactive half ko mask karke:
Non-diverging cost hai. Toh yeh slowdown hai, aur half lanes har path ke dauran idle rehte hain.
Key subtlety: cost liye gaye distinct paths ki sankhya ke saath scale hoti hai, threads ki sankhya ke saath nahi. Agar saare 32 ne branch A liya, toh cost hi rehti hai — bilkul bhi divergence penalty nahi.
Level 4 — Synthesis
L4.1 — Do limits ke under block size choose karo
Problem. Ek SM mein registers hain, zyada se zyada warps ( threads) aur zyada se zyada blocks resident allowed hain, aur KB shared memory hai. Tumhara kernel registers/thread aur KB shared memory per block use karta hai. Tum block size (sab 32 ke multiples) mein se choose kar sakte ho. Kaunsa highest occupancy deta hai?
Recall Solution
Har block size ke liye, har limit se resident-block cap compute karo, minimum lo, phir warps mein convert karo.
Registers. Per thread cost , toh per SM register file threads support karta hai regardless of block size → yahan binding limit nahi (yeh exactly -thread warp cap se match karta hai).
Shared memory. Har block KB chahta hai aur SM ke paas KB hai, toh blocks max (KB units cancel ho jaate hain, pure count bachta hai).
Block/thread caps, per block size ke hisaab se:
- 128 threads (4 warps): thread cap blocks; block cap ; SMEM . Min blocks warps → 100%.
- 256 threads (8 warps): thread cap blocks; SMEM ; block cap . Min warps → 100%.
- 512 threads (16 warps): thread cap blocks; SMEM . Min warps → 100%.
Answer: teeno warps = occupancy tak pahunchte hain, kyunki yeh kernel registers aur shared memory par light hai. Insight: jab koi resource scarce nahi hai, occupancy raw warp cap se decide hoti hai, aur block size ek secondary choice ban jaata hai (aisa size lo jo caps mein evenly fit ho aur tumhari shared-memory tiling ke liye accha ho — yahan 256 ek safe default hai).
L4.2 — Ab shared memory ko villain banao
Problem. L4.1 jaisa hi SM, lekin kernel ab KB shared memory per block use karta hai (ek bada tiling buffer). Block size ( warps). Occupancy kya hai, aur binding limit kya hai?
Recall Solution
Shared memory cap: blocks. Register cap: blocks. Block cap: . Min blocks. Warps: . Occupancy: . Binding limit: shared memory. Kya karna chahiye: tile chhota karo (per block kam SMEM) ya buffer ko split karo, thoda data reuse trade karo zyada resident blocks ke liye. Yeh classic Occupancy-optimization tug-of-war hai reuse aur parallelism ke beech.
Level 5 — Mastery
L5.1 — End-to-end: ek slow kernel diagnose aur fix karo
Problem. Ek memory-bound kernel occupancy ( mein se warps) par run karta hai. Profiling: yeh registers/thread use karta hai, block size , registers aur -warp cap wale SM par, negligible shared memory. Global loads cycles stall karte hain. (a) Yeh slow kyun hai? (b) Agar tum refactor karke registers/thread par aao, toh nayi occupancy kya hogi? (c) Roughly -cycle stall ka kitna zyada ab chhupaya ja sakta hai?
Recall Solution
(a) Diagnosis. L2.1/L2.2 se: regs/thread → blocks → warps → . Ek -cycle stall ko poori tarah chhupane ke liye warps chahiye (L3.1 logic); warps per scheduler pass sirf cycles cover karte hain, toh SM har stall ka zyaatar hissa idle baitha rehta hai. Root cause: register pressure resident warps ko us level se kahin neeche cap kar deti hai jo latency-hiding ko chahiye.
(b) regs/thread par refactor ke baad. Registers per block: . Blocks: . Warps: . Occupancy: .
(c) Latency hidden. Warps double hue , toh per scheduler pass hideable slice roughly double ho jaata hai ( cycles). Phir bhi se kaafi kam hai, toh occupancy akele yeh poori tarah theek nahi kar sakti — tum saath mein memory-coalescing aur reuse (shared-memory tiling) bhi pursue karoge taaki stalls ki sankhya kam ho. Mastery point: occupancy us ceiling ko raise karti hai jitni latency tum chhupa sakte ho, lekin complementary — aur aksar bada — lever yeh hai ki latency khud ko reduce karo, accesses coalesce karke aur data shared memory mein reuse karke taaki chhupane ke liye pehle hi kam stalls hon.
L5.2 — Ek aisa launch design karo jo warps saturate kare aur shared memory use kare
Problem. Target: exactly resident warps () ek SM par jinmein registers, -warp cap, KB shared memory hai. Tum block size ( warps) use karoge. resident blocks rakhne ke liye (jaroori hai warps ke liye) tum maximum kitne registers/thread aur shared memory/block afford kar sakte ho?
Recall Solution
blocks resident rakhne ke liye: Registers. Saare resident threads mein total . Threads resident . Toh per-thread budget: Shared memory. blocks KB share karte hain: Check: blocks block cap () ✓; warps cap ✓. Answer: hit karne ke liye regs/thread aur KB SMEM/block par ya neeche raho. Kisi ek ko bhi exceed karo aur resident blocks se neeche gir jaate hain, aur occupancy khatam ho jaati hai. Yeh Occupancy-optimization ka poora budget-balancing act hai — aur isliye Tensor Cores aur thread block sizing ko haath mein haath milaake tune kiya jaata hai.
Recall Self-test recap (cloze)
Ek warp hamesha 32 threads hota hai. Occupancy = active warps divided by ::: max warps per SM. Resident block count ::: minimum hota hai sab resource limits ka (registers, shared memory, warp cap, block cap). Extra warps ::: latency hide karte hain — yeh ALU throughput nahi badhate. Divergence cost ::: liye gaye distinct branch paths ki sankhya ke saath scale hoti hai, threads ki sankhya ke saath nahi.
Upar use kiye gaye prerequisite links: CUDA-cores · Warp-scheduling · Shared-memory · Thread-blocks · Occupancy-optimization · GPU-memory-hierarchy · Tensor-cores · Hinglish version.