Exercises — SIMT (single instruction multiple thread)
This page is a self-test ladder. Each problem is stated cleanly, then a hidden solution walks every step. Work it yourself first, then reveal.
Everything here builds directly on the parent SIMT note. Before we start, we re-anchor every symbol so nothing is assumed.

Level 1 — Recognition
Exercise 1.1
A kernel is launched with 100 threads. Warps are formed by cutting the threads into groups of 32 in order. How many warps are created, and what is the warp utilization of the last warp?
Recall Solution
WHAT we do: count groups of 32, then look at the leftover. WHY: the hardware can only schedule whole warps; it always allocates a full 32-lane warp even if some lanes have no thread.
Number of warps warps.
Warps 0, 1, 2 each hold 32 threads. That uses threads. The last warp (warp 3) holds threads.
Utilization of the last warp:
WHAT IT LOOKS LIKE: in the light-bulb picture, warp 3 has 4 bulbs lit and 28 dark — see the red group in the figure. Those 28 dark lanes still cost hardware slots; they are wasted.
Exercise 1.2
Which execution model allows threads to take different branches: SIMD or SIMT? One word.
Recall Solution
SIMT. In SIMD (e.g. AVX) every lane is forced to execute the same operation — divergence is impossible. In SIMT each thread has its own logical program counter, so branches are allowed (paid for with serialization). See SIMD vs SIMT Comparison.
Level 2 — Application
Exercise 2.1
A block has 256 threads. (a) How many warps is that? (b) A grid launches 1000 such blocks — how many warps total?
Recall Solution
WHAT we do (a): divide the block's threads by 32 and round up. WHY: a block is diced into warps of 32 inside the SM it runs on; the hardware scheduling unit is the warp, never the loose thread, so the block's threads must be packaged into whole warps. 256 is an exact multiple of 32, so no lane is wasted.
WHAT we do (b): multiply warps-per-block by the number of blocks. WHY: a grid is just a collection of independent blocks, and each block contributes the same 8 warps; total work is therefore the per-block warp count summed across all blocks, which is a plain multiplication. See CUDA Thread Hierarchy.
Exercise 2.2
A warp hits this branch, with a 50/50 split — 16 threads take the hot path, 16 take the cold path. Here tid is the thread ID defined at the top (), so data[tid] is this thread's own element:
if (data[tid] > threshold) // tid = blockIdx*blockDim + threadIdx
hot(); // 10 cycles
else
cold(); // 30 cyclesHow many cycles does this warp spend, and what is the effective utilization?
Recall Solution
WHAT we do: because the two groups take different paths, the warp runs them serially — first one branch with the others masked, then the other. WHY: a single warp can only be at ONE instruction address per cycle. So it executes branch A fully (16 lanes lit, 16 dark), then branch B fully (the mask flips).
During the hot phase, 16 of 32 lanes are lit → 50% utilization. Same for the cold phase. Average lit-lane utilization = 50%.
WHAT IT LOOKS LIKE: two passes of the bulb row; each pass has exactly half the bulbs dark (figure s02).

Level 3 — Analysis
Exercise 3.1
A warp of 32 threads runs code where every thread takes a unique path through a 32-way switch, and each path costs 10 cycles. Compare the time against a fully-converged warp (all 32 on the same 10-cycle path). What is the slowdown factor?
Recall Solution
WHAT we do: count how many serial passes are forced. WHY: each distinct path is a separate serialized phase; 32 unique paths = 32 phases, each with only 1 lane lit.
This is the worst case of SIMT: a penalty, one lane lit per pass. See Warp Divergence.
Exercise 3.2
32 threads read from global memory. The address of thread is
Compute the coalescing efficiency for (a) stride = 4 bytes and (b) stride = 128 bytes. A memory transaction moves one 128-byte cache line. Assume base is 128-byte aligned (we treat the misaligned case separately in the note below).
Recall Solution
Coalescing efficiency . See GPU Memory Coalescing.
The warp always needs bytes of useful data.
(a) stride = 4 bytes. The 32 addresses are — a contiguous 128-byte span. Because base is aligned to a 128-byte boundary, that span lands inside a single line, so it fits in one 128-byte transaction.
(b) stride = 128 bytes. Now consecutive threads are one full cache line apart, so each of the 32 threads lands in a different 128-byte line → 32 transactions, moving bytes.
WHAT IT LOOKS LIKE: case (a) is one tight red bar of accesses; case (b) is 32 scattered red ticks, each dragging a whole line (figure s03).

Level 4 — Synthesis
Exercise 4.1
You must hide a memory latency of cycles. The SM needs throughput instruction per cycle to stay busy, and each warp can issue an instruction only once every 4 cycles on average (the rest of the time it is waiting). How many warps must the SM keep resident? If the SM supports at most 64 warps, is a single SM enough?
Recall Solution
WHAT we do: use the latency-hiding rule and then adjust for the per-warp issue gap. WHY: while one warp waits, others must supply work. To never stall, the pool of warps must be large enough that at every cycle at least one is ready.
Base requirement to hide latency:
But each warp issues only every 4 cycles, so a single warp covers 4 of those cycles of work:
The SM caps at 64 warps, and . So one SM is not enough — this is exactly why GPUs use many SMs in parallel rather than one deep pipeline, and why kernels chase high occupancy. See also GPU vs CPU Architecture.
Exercise 4.2
Same launch as Exercise 2.1 (8000 warps total). The GPU has 80 SMs, each running 16 warps concurrently. How many "waves" are needed, and what is the total time if one wave costs ?
Recall Solution
WHAT we do: find how many warps run at once, then divide the total by it and round up. WHY divide: the GPU has a fixed number of warp slots resident at any instant — 80 SMs each holding 16 warps. A "wave" is one full filling of every slot; only that many warps can physically be in flight together, so the total work must be poured through the machine in batches of that size.
Concurrent warps across the whole GPU:
Waves needed to drain 8000 warps:
WHY round up: after 6 full waves, warps are done, leaving warps still unexecuted. Those 320 warps must occupy real slots for a whole extra scheduling pass — the hardware cannot run "0.25 of a wave", it lights up a fresh wave (mostly under-filled) to finish them. Leftover work therefore always forces one more complete wave.
Total time (ignoring overlap between waves):
Level 5 — Mastery
Exercise 5.1
An Ampere-style SM has:
- 65536 registers total,
- 1024 threads maximum per SM,
- a hard cap of 64 warps per SM,
- 65536 bytes (64 KB) of shared memory total.
Your kernel uses 64 registers per thread, runs in blocks of 256 threads (= 8 warps per block), and each block requests 16384 bytes (16 KB) of shared memory. Find the occupancy: how many warps can actually run, and what fraction of the 64-warp maximum is that?
Recall Solution
WHAT we do: compute the warp limit from each resource — registers, threads, hardware cap, and shared memory — then take the smallest (the binding constraint). WHY: an SM has several finite resource pools, and all of them must fit simultaneously. A warp can only be resident if every pool it draws from still has room; therefore the SM stops adding warps the moment the first pool runs dry. That is why occupancy is a over independent limits, not a product or a sum.
Register limit. A warp is 32 threads, so registers per warp .
Thread limit. warps.
Hardware cap. 64 warps.
Shared-memory limit. Each block needs 16 KB, and the SM has 64 KB, so at most blocks fit. Each block is 8 warps, so shared memory allows warps.
The binding constraint is the smallest: warps.
Here three separate limits (registers, threads, shared memory) all pin us at 32 warps. To push occupancy higher you would need to relieve all of the binding ones at once — e.g. cut registers to 32/thread and shared memory to 8 KB/block. This is the classic GPU Occupancy trade-off, tied to Instruction-Level Parallelism.
Exercise 5.2 (Capstone)
Combine everything. A warp runs the branch from Exercise 2.2 (40 cycles, 50/50 split, hot=10 / cold=30). Suppose you sort the data so that a warp is now fully converged onto the cold path. (a) What is the new time for that warp? (b) What speedup did sorting buy versus the diverged 40 cycles?
Recall Solution
WHAT we do: re-evaluate the warp's cost once it is fully converged, then divide the old cost by the new. WHY (a): when all 32 lanes take the same branch, there is no second serialized pass — the warp is at one instruction address the whole time, so its cost is just that single branch's time, not a sum. This is the exact opposite of Exercise 2.2, where two different addresses forced two passes. WHY (b): speedup is defined as old-time over new-time because it measures how many times faster the work now finishes; removing the extra serial pass is precisely what the ratio captures.
(a) Fully converged means all 32 lanes take the same branch, so time is just that one branch: No serialization — one pass, all bulbs lit.
(b) Speedup:
Sorting removed the second serial pass. The gain looks modest here because hot (10) was cheap; if both branches were equal-cost the diverged case would be slower and sorting would double throughput. This is why "sort/group by branch outcome" is a top-tier SIMT optimization. See Warp Divergence.
Recall Quick self-check (reveal the answers)
Round threads up to whole warps? ::: Yes — always . Diverged branch cost is sum or max? ::: Sum (); only converged warps cost . Worst-case divergence slowdown for a 32-thread warp? ::: (every thread unique path). Coalescing efficiency for stride = one full cache line? ::: . What breaks the ideal 1-transaction coalesced case even when accesses are contiguous? ::: A misaligned base — the 128-byte span straddles two lines, costing 2 transactions (50%). Occupancy from multiple resource limits? ::: The minimum limit (registers, threads, cap, shared memory), not the sum.