GPU Hardware
A GPU is a throughput machine: thousands of tiny cores grouped into streaming multiprocessors, fed by a steep memory hierarchy. These animations walk through how a kernel's grid of thread blocks gets scheduled, how warps execute in lockstep, where data lives, and why decode is so often bottlenecked by memory bandwidth rather than raw compute.
The GPU execution model: grid → blocks → SMs → warps
step-throughA kernel launches a grid of thread blocks; the hardware dispatches blocks onto many streaming multiprocessors, where threads run in 32-thread warps in SIMT lockstep.
The contrast with a CPU is the whole point. A CPU has a few big, stateful cores tuned for
latency and complex control flow; a GPU has thousands of simple, stateless cores
organized for throughput. An SM — a Streaming Multiprocessor — is the unit that most
resembles a CPU core: it bundles cores, registers, caches, and a scheduler, and runs a huge amount
of simultaneous multithreading. (AMD calls these Compute Units, and the green CUDA Cores
are Stream Processors.)
Throughput vs latency: many small cores, not a few big ones
auto-playA CPU finishes a few items fast with big out-of-order cores; a GPU floods a huge grid of simple cores and wins on total work per second. Watch both chew through the same workload.
The memory hierarchy: registers → SRAM → L2 → HBM
step-throughAs you climb down the hierarchy capacity grows but bandwidth and latency get worse. Keeping data high in the hierarchy is the single biggest lever for kernel performance.
N×N score matrix out to HBM and reads it back — a flood of slow global traffic.
FlashAttention instead streams tiles of Q, K and V into on-chip SRAM
(shared memory / L1), computes the softmax incrementally there, and never materializes the big
matrix in HBM. Same math, far less data movement — which is exactly why it is faster.
Kernels & Triton: one program instance, one tile
step-throughA kernel is a function run across the whole grid. CUDA (NVIDIA) and ROCm (AMD) are the native stacks; Triton lets you write tiled kernels in Python where each program instance owns one tile — load to SRAM, compute, write back.
One kernel, many program instances (Triton) or thread blocks (CUDA/ROCm) — each handling a different tile of the same tensor, all running at once across the SMs. The art of a fast kernel is choosing a tile that fits in SRAM and registers so the cores stay busy instead of waiting on HBM.
Memory-bound vs compute-bound: why decode waits
step-throughArithmetic intensity = math done per byte moved. Low intensity work is starved by bandwidth; high intensity work finally saturates the cores. This is the roofline intuition.