Master the fundamental concepts of gpu architecture through this focused micro-challenge.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksA CPU thread is an independent execution context with its own program counter, registers, and stack. Context switching is expensive because the OS must save and restore the full register file. Modern CPUs run tens of threads across a handful of cores.
A GPU thread is much lighter. On NVIDIA hardware, 32 threads form a warp; on AMD, 64 threads form a wavefront. All threads in a warp execute the same instruction on different data. This is Single Instruction, Multiple Thread (SIMT) execution.
The critical difference is divergence. If threads in the same warp take different branches, the hardware serializes them:
cLoading…
For example, a warp where 16 threads take branch A and 16 take branch B runs both paths sequentially, halving throughput. Memory access matters too: if thread i reads address base + i * 4, the warp issues one coalesced transaction. If each thread reads base + i * 1024, the warp may issue up to 32 separate transactions.
You will implement a warp simulation that shows branch divergence in two serialized phases and compares coalesced vs scattered memory access. This task requires you to count transactions and explain why GPU threads are not scheduled like CPU threads. Every later GPU architecture exercise in this subtrack assumes you think at warp granularity, not individual thread granularity.
A GPU runs threads in lockstep groups: warps of 32 on NVIDIA, wavefronts of 64 on AMD GCN. All lanes of a group share one instruction stream. When a branch diverges, the group runs both sides one after the other, masking off the lanes that didn't take each side. A loop runs as long as its slowest lane. Build a cost model that shows this: run a small kernel over N threads, split into groups of 32 or 64, and report cycles and lane utilization per group.
# starts a comment.
cLoading…
VAR [OP K] [CMP R].
tid (the global thread id) or lane (tid mod width).%, / or &, with K > 0.==, !=, < or >=.& (non-zero means true).Group g holds threads g·width … g·width+width-1. Lanes past N are inactive from the start.
if reached with at least one active lane counts as a branch execution, and it is divergent if both masks are non-empty.C × max(TRIPS over active lanes), and adds TRIPS × C useful lane-cycles per active lane.cLoading…
wavefront(s). Plurals: lane(s), branch(es).line N: threads 1-1024line N: work CYCLES (1-1000000)line N: bad condition, line N: loop TRIPS CYCLESline N: else without if, line N: end without ifline N: unknown statement Xprogram has errors (for run after any error)run: N unclosed ifrun: width must be 32 or 64Input:
cLoading…
Output:
cLoading…
Hidden tests cover a branch that is uniform for warps but divergent for wavefronts, per-lane loop trip counts, nested branches with lane and &, a partially filled group, and statement errors.