v9.1.1
Menu

Chapter 2: GPU Architecture & the Memory Hierarchy

Week 1-2

Map the physical GPU: how threads group into warps and blocks, how Streaming Multiprocessors schedule them, the register→shared→L2→global memory hierarchy, why coalesced memory access is critical, and how arithmetic intensity and the roofline decide whether you are compute- or memory-bound.

Topics
5
Demo
1
Videos
3
Min read
16

Chapter Overview

Chapter 1 gave you the mindset; this chapter gives you the map. To write fast kernels you must know where your data lives and how the hardware moves it.

A GPU is organized as a grid of Streaming Multiprocessors (SMs), each containing many ALUs, a register file, an on-chip scratchpad (shared memory / L1), and warp schedulers. Your kernel launches a grid of blocks; the GPU assigns blocks to SMs, and each SM runs the block's threads as warps. Threads in a block can cooperate through fast shared memory; threads in different blocks essentially cannot.

The single most important structure here is the memory hierarchy. Registers are nearly free but tiny and private. Shared memory (SRAM) is fast and block-local — and in Triton it's the resource you orchestrate every time you 'tile' a computation. L2 is a device-wide cache. Global memory (DRAM) is huge but slow, and its bandwidth is the bottleneck for most kernels. Almost every optimization in this course reduces to: read from DRAM as few times as possible, do as much work as you can while the data is on-chip.

This chapter covers:

  • Threads, Warps & Blocks: the execution hierarchy
  • Streaming Multiprocessors: where blocks actually run
  • The Memory Hierarchy: registers → SRAM → L2 → DRAM
  • Memory Coalescing: turning many small reads into one fast transaction
  • Arithmetic Intensity & the Roofline: are you compute- or memory-bound?

Chapter Roadmap

Click any topic to jump in

Explainer videoInteractive demo
1
Threads, Warps & Blocks

The execution hierarchy: warps of 32 run in lockstep; blocks cooperate via shared memory; blocks are independent.

The Execution Hierarchy
Where the hierarchy lives
2
Streaming Multiprocessors

Where blocks run — registers, schedulers, ALUs, and SRAM. Resource limits set occupancy.

Inside an SM
The levels you optimize across
3
The Memory Hierarchy

Registers → SRAM → L2 → DRAM. Keep hot data high and reuse it before it falls back down.

Registers, SRAM, L2, and DRAM
How you read DRAM efficiently
4
Memory Coalescing

Contiguous warp reads become one transaction; strided reads waste most of the bandwidth.

Coalesced vs Strided Access
Diagnosing the bottleneck
5
Arithmetic Intensity & Roofline

FLOPs/byte decides whether you're memory- or compute-bound — and therefore what to optimize.

FLOPs per Byte

Topics

5 topics in this chapter

Chapter 1 argued that a GPU needs tens of thousands of threads in flight to hide memory latency. That raises an organizational problem: how do you name, schedule and coordinate that many threads without the programmer tracking each one? GPUs answer with a fixed three-level hierarchy. Threads, the unit you write code for, are bundled into warps of 32 that share one instruction stream, the SIMT model from the previous chapter. Warps are grouped into blocks, which the hardware places on a single streaming multiprocessor so their threads can share fast on-chip memory and wait at barriers. Blocks form the grid, which is everything one kernel launch does. Each level has its own rules about what threads may share and when they may synchronize, and confusing them produces kernels that are either slow or silently wrong. This topic walks the hierarchy with concrete counts: a grid of 1,024 blocks of 256 threads is 262,144 threads in 8,192 warps. It then shows why blocks must be independent of each other, and how Triton's program instance maps onto the block level. The next topic opens up the SM itself.

Definition

The GPU execution hierarchy has four levels. A thread is one scalar instance of the kernel; a warp is 32 threads issued together; a block (cooperative thread array) is a group of warps resident on one SM that can share memory and synchronize at barriers; and a grid is the set of independent blocks launched by one kernel call.

1 of 1
The Execution Hierarchy

Threads are the smallest unit; each has its own registers and program counter. Warps are fixed groups of 32 threads that execute in lockstep (the SIMT unit from Chapter 1). Blocks (a.k.a. thread blocks or CTAs) are groups of warps that run together on a single SM and can cooperate via shared memory and barriers (__syncthreads). The grid is all the blocks for one kernel launch.

Key rules: threads in the same block can share data and synchronize; threads in different blocks cannot (blocks may run in any order, even on different SMs, possibly not at the same time). This independence is what lets the GPU scale — it can schedule blocks however many SMs it has.

In Triton you mostly think one level up: a program corresponds to a block-sized tile of work, and Triton manages the threads within it for you.

Mathematical Intuition

An SM has hard limits: max resident threads, warps, blocks, registers, and shared memory. Occupancy = (resident warps) / (max warps). If each block uses RR registers/thread and SS bytes of shared memory, the SM can host min⁡ ⁣(regsR⋅threads,smemS,block limit)\min\!\left(\frac{\text{regs}}{R \cdot \text{threads}}, \frac{\text{smem}}{S}, \text{block limit}\right) blocks. Choosing block size and resource usage is really choosing occupancy.

Example:

You launch a kernel with a grid of 1024 blocks, each with 256 threads. How many threads and warps is that, and what can block #0's threads do that block #5's cannot?