6.2.15 · D2 · HinglishGPU Architecture

Visual walkthroughROCm - OpenCL alternatives

2,900 words13 min read↑ Read in English

6.2.15 · D2 · Hardware › GPU Architecture › ROCm - OpenCL alternatives

Yeh page parent note ka ek central result pictures mein derive karta hai: ek formula jo GPU pe har single worker ko uska apna unique home address deta hai. Hum abhi woh formula likhne wale nahi hain — uske har symbol ko pehle earn karna hoga. End tak aap dekh paoge ki poori cheez bas "boxes ke andar boxes ginना" hai, aur aap jaanoge ki har edge pe kya hota hai — last box, leftover box, aur empty case.

Pehle parent padho agar nahi padha: ROCm / OpenCL alternatives.


Step 1 — Problem: identical jobs ka ek bada pile

KYA. Soch lo ki hamare paas numbers ki ek giant list hai aur hum har ek pe same chhota sa operation karna chahte hain — jaise, do arrays ko element by element add karna: C[i] = A[i] + B[i]. Maano list mein elements hain (hum chhota number use karte hain taaki picture mein fit ho; real note mein over a million use hote hain).

KYO. Ek GPU ek fast worker nahi hota. Yeh hazaaron slow-ish workers hota hai. Use karne ke liye, hume har worker ko exactly ek job dena hoga aur ensure karna hoga ki do workers ek hi job na pakdein aur koi job skip na ho. Toh sabse pehla sawaal yeh hai: hum job numbers kaise distribute karein taaki har worker jaane ki unka wala kaunsa hai?

PICTURE. Yeh rahe jobs ka raw pile — numbered boxes ki ek single row.

Figure — ROCm - OpenCL alternatives

Step 2 — Pehla symbol: the global ID

KYA. Aap bol sakte ho: "Bas inhe se tak ek lambi line mein number karo aur ho gaya." Woh flat position — poore problem mein worker ka address — itna important hai ki isko abhi hi ek naam aur symbol milna chahiye.

KYO. Hum ise abhi symbol dete hain kyunki yahi woh quantity hai jo hum ultimately dhundh rahe hain. Is page ki har baaki cheez sirf ko un chhote pieces se reconstruct karne ke liye exist karti hai jo hardware actually deta hai. Is box-number picture ko pakde raho; har baad wala symbol iske against measure kiya jaayega.

PICTURE. Wahi row phir se, ab uske neeche naam likha hua.

Figure — ROCm - OpenCL alternatives

Step 3 — Hum sabko ek saath number kyun nahi kar sakte

KYA. Toh yahan kyun nahi rukke aur directly use karein? Kyunki hardware humein woh flat numbers distribute nahi karne deta. Yeh pehle line ko equal chunks mein kaat'ne par insist karta hai. Har chunk ko work-group kehte hain.

KYO. Real silicon workers ko fixed-size batches mein execute karta hai — NVIDIA inhe at a time chalaata hai (ek warp), AMD inhe at a time chalaata hai (ek wavefront). Toh hum force hain ki flat line ko equal groups mein slice karein jo hardware ke batch size se match karein.

PICTURE. Wahi boxes, lekin ab ke groups mein slice kiye gaye. (Hum ki jagah pick karte hain sirf taaki screen pe fit ho — logic identical hai.)

Figure — ROCm - OpenCL alternatives


Step 4 — Ek ruler ki jagah do rulers

KYA. Hardware kabhi worker ko uska directly nahi batata. Iski jagah yeh har worker ko do chhote addresses deta hai:

  • Uska group IDwoh kis box mein rehta hai ().
  • Uska local IDus box ke andar uski seat ().

KYO. Hardware sirf itna jaanta hai "tum group #1 ke andar worker #2 ho". Yeh Step 3 ke batching ka natural consequence hai. Toh humein do chhote rulers diye jaate hain aur hume ek bade ruler () ko khud reconstruct karna hota hai.

PICTURE. Wahi strip, do baar label ki gayi: bottom ruler groups count karta hai, top ruler har group ke andar se restart karta hai.

Figure — ROCm - OpenCL alternatives

Notice karein ki top ruler har group ke start pe reset to 0 hota hai. Wahi reset hi wajah hai ki hume formula chahiye: local ID chaar alag-alag baar appear karta hai, toh yeh akele address nahi ho sakta.

group_id
ek worker kis group se belong karta hai — poore boxes par ek index
local_id
apne box ke andar worker ka seat number, jo har box mein 0 se restart karta hai

Step 5 — Formula banana: pehle full boxes skip karo, phir andar step karo

KYA. Ab hum finally do rulers se assemble karte hain. Worker local ID 2 in group 1 lo. Uska global number find karne ke liye hum do cheezein karte hain:

  1. Hamare pehle ke har box ko skip karo. Humare aage full box hai, jisme workers hain, toh hum addresses skip karte hain.
  2. Apni seat par walk karo. Apna local seat number add karo, .

Yeh deta hai . Step 4 se check karo: haan, global label wala box exactly local-2-of-group-1 hai.

KYO. Yeh mixed base mein likh'a number padhne se zyada kuch nahi hai. "Group , seat , with seats per group" wahi idea hai jaise " ten aur ones ", except har place ki jagah worth hai.

PICTURE. Red arrow pehle full groups ke upar jumps karta hai (woh multiply hai), phir seat pe steps karta hai (woh add hai).

Figure — ROCm - OpenCL alternatives


Step 6 — Ulta jaana: global number se box aur seat recover karna

KYA. Kabhi kabhi hamare paas global number hota hai aur hum doosri direction chahte hain: kaun sa box, kaun si seat? Woh bas integer division aur remainder use karke formula ko ulta solve karna hai:

KYO. Integer division jawaab deta hai "mere neeche kitne whole boxes fit hote hain?" aur remainder jawaab deta hai "last full box ke baad main kitna aage hun?" — exactly Step 5 ke skip-then-step ka inverse.

PICTURE. Worker global : se divide karne pe quotient milta hai (box) aur remainder (seat). Dono operations Step 5 ke arrow ke do parts ki taraf point karte hain.

Figure — ROCm - OpenCL alternatives


Step 7 — Edge case A: sabse pehla aur sabse aakhri worker

KYA. Extremes check karo taaki kuch kabhi undefined na ho.

  • Pehla worker: group , local . Correct: line ka front.
  • Aakhri worker: group , local . Correct: final box, final seat, jo ki hai.

KYO. Hume prove karna hoga ki formula boundaries cover karta hai, kyunki off-by-one errors yahan classic GPU bug hain: ek box zyada door padh lo aur tum us memory ko touch karte ho jo tumhari nahi.

PICTURE. Dono ends lit up — global range exactly se tak run karti hai, koi gap nahi, koi overshoot nahi.

Figure — ROCm - OpenCL alternatives

Step 8 — Edge case B: jab total evenly divide nahi hota (the "guard" clause)

KYA. Maano hamare paas real jobs hain lekin hardware ke groups force karta hai. Tab , jo whole number nahi hai. Runtime launch ko groups workers tak round up karta hai — lekin sirf jobs exist karti hain. Workers aur ke paas koi real job nahi hai.

KYO. Hardware sirf whole groups launch kar sakta hai. Toh hum hamesha kuch extra workers spawn karte hain aur unhe array ke end ke baad read karne se pehle switch off karna padta hai. Wahi exactly har kernel mein if (i < n) guard hai:

int i = blockIdx.x * blockDim.x + threadIdx.x; // = global_id
if (i < n) y[i] = a * x[i] + y[i];             // <-- the guard

PICTURE. Do extra workers (global ) ghosts ki tarah draw kiye gaye hain; red guard line unhe drop karti hai taaki woh kuch na karein.

Figure — ROCm - OpenCL alternatives

Step 9 — Edge case C: degenerate launches, including the empty one

KYA. Check karne ke liye teen limiting shapes.

  • Ek giant group (): tab group_id hamesha hoga, aur . Do rulers ek mein collapse ho jaate hain — formula phir bhi hold karta hai.
  • Groups of one (): tab local_id hamesha hoga, aur . Phir se ek ruler; formula phir bhi hold karta hai.
  • Koi jobs hi nahi (): line empty hai, , toh zero workers launch hote hain. Formula kabhi evaluate nahi hota — koi worker nahi hai jo hold kare — aur kuch galat nahi hota. Ek empty workload ek valid, quietly-does-nothing launch hai.

KYO. Ek formula jis par aap trust karte ho use apne extremes survive karne chahiye. aur par "boxes inside boxes" picture ek single ruler mein flat ho jaati hai; par picture blank hai aur Step 8 ka guard (if (i < n) with ) ka matlab hai koi worker kabhi nahi chalta. Har case mein arithmetic agree karta hai.

PICTURE. Top: ek box jisme saare hain. Middle: boxes jisme ek ek hain. Bottom: empty line — koi boxes nahi, koi workers nahi.

Figure — ROCm - OpenCL alternatives
Recall Degenerate cases kyun matter karte hain?

Kyunki ek mapping jo , , ya par toot jaaye woh ek unreliable abstraction hogi. Yeh fact ki group_id * local_size + local_id collapsing cases mein gracefully ek plain identity mein reduce ho jaata hai, aur empty launch par simply kabhi fire nahi karta, proof hai ki yeh sahi, general formula hai — koi special-case hack nahi.


Ek-picture summary

Upar sab kuch ek idea hai: jobs ki ek flat line secretly boxes ka ek grid hai, aur address formula woh hai jisse tum dono views ke beech fold karte ho. Full boxes skip karne ke liye multiply karo, apni seat mein step karne ke liye add karo; wapas jaane ke liye divide aur remainder karo.

Figure — ROCm - OpenCL alternatives
Recall Feynman retelling — aise bolo jaaise kisi dost ko bata rahe ho

Ek GPU mein hazaaron tiny workers hain, aur ek hi problem yeh hai ki har ek ko bina clashes ke ek job dena ho. Pure job list mein uska saccha seat number hum global ID kehte hain. Lekin chip unhe saari ek row mein line up nahi karega — yeh unhe fixed-size gangs mein chalaata hai (NVIDIA ke liye 32, AMD ke liye 64), aur har gang mein workers hain. Toh har worker ko do chhoti cheezein bataayi jaati hain: woh kaun si gang mein hai (group ID) aur gang ke andar kaun si seat (local ID). Apna global ID rebuild karne ke liye woh saare pehle wale gangs ko skip karta hai — woh hai "gang number times " — phir apni seat tak chalta hai — "plus seat number". Ulta karne ke liye, se divide karo (kaun si gang) aur remainder lo (kaun si seat). Hum hamesha thode zyada workers launch karte hain kyunki gangs whole sizes mein aate hain, toh hum ek line add karte hain, if (i < n), baaki walon ko still baithe rehne ko kehne ke liye. Ends check karo: worker zero pe land karta hai, aakhri real worker pe, kabhi pe nahi. Ek gang ko size one tak squash karo, ya ise sabko hold karne ke liye blow up karo, aur formula phir bhi same flat line deta hai — aur agar zero jobs hain, zero workers launch hote hain aur kuch nahi hota. Bas yahi hai — boxes ke andar boxes ginना.

recall — the address formula
global_id = group_id × L + local_id (L = local work size)
recall — going backwards, which seat?
local_id = global_id mod L
recall — why extra workers exist
gangs whole sizes mein aate hain, toh G ko L ke multiple tak round up kiya jaata hai; leftovers if (i < n) se kill ho jaate hain
recall — what happens when G = 0
Num Groups = 0, koi workers launch nahi hote, formula kabhi fire nahi karta