GPU Architecture · Reference Card
Where a thread's state lives, who decides how much it gets, and why that caps how many threads run at once.
The compiler backend ptxas fixes a per-thread register count for each kernel at compile time. Every thread of that kernel uses the same number. You don't declare it; you influence it.
nvcc -Xptxas -v (or --resource-usage) prints Used N registers per kernel.--maxrregcount=N, or __launch_bounds__(maxThreads, minBlocks) on the kernel.Occupancy = resident warps ÷ the SM's maximum warps. Registers are one of two budgets that limit it. Example on H100 (65,536 registers/SM, max 64 resident warps = 2,048 threads):
| Registers / thread | Threads that fit | Resident warps | Occupancy |
|---|---|---|---|
| 32 | 2,048 | 64 | 100% |
| 64 | 1,024 | 32 | 50% |
| 128 | 512 | 16 | 25% |
| 255 | ~257 | ~8 | ~12% |
More registers per thread → fewer threads resident → a smaller backlog of warps → less latency-hiding headroom. High occupancy isn't always the goal (a register-hungry kernel can still be fast), but you should always know which budget you're spending.
1. The data register file — 256 KB/SM, carved per thread.
2. The warp/control slots — a fixed count of resident-warp slots per SM (H100: 64). A kernel hits whichever it exhausts first. (Shared memory per block is a third; see the memory lessons.)
The 256 KB register file holds data. A thread's control state sits in dedicated scheduler hardware, one slot per resident warp — separate budget, never in the data RF:
__syncthreads().Both a thread's register slice and its warp's control slot stay allocated the entire time its block is resident on the SM. Switching warps = the scheduler indexing into structures that are already there. Nothing is saved or restored — unlike a CPU, which must spill one thread's registers to memory to run another.