The profiler delivers its verdict: your kernel is achieving 4% of the GPU's peak
flops. Four percent! Of the machine you
Recall the machinery: a kernel's arithmetic intensity
Twenty flops per byte touched just to break even with the ALUs. Now audit some kernels:
| Kernel | Intensity | Verdict on a ridge-20 machine |
|---|---|---|
| vector add | 1 flop / 12 B ≈ 0.08 | memory-bound, 250× below the ridge — roof is 83 Gflop/s, 0.4% of peak |
| stencils, elementwise ML ops | 0.5 – 2 | memory-bound — this is most real code |
| tiled matrix multiply | hundreds (grows with tile size) | compute-bound — the rare kernel that can touch peak flops |
The uncomfortable truth of GPU performance work is in that middle row: most kernels live far left of the ridge, where the memory roof — not the shiny Tflops number — is the law.
Practitioners draw the roofline on log–log axes so that five orders of
magnitude of intensity fit on one chart: the memory roof becomes a 45° line, the compute
roof stays flat, and they meet at the ridge. Drag the slider — it is your kernel's
intensity — and watch the marker ride up the memory roof, hit the ridge at
Everything left of the ridge can be read as a percentage: at
The roofline says what the hardware could deliver at your intensity; whether you get it depends on keeping the machine busy while memory crawls. A DRAM access costs hundreds of cycles, and the GPU's whole survival strategy is to have other warps ready to issue during the wait. The first-order health metric for that strategy is occupancy:
Why would it ever be below 1? Because residency is rationed by the SM's fixed budgets:
the register file and shared memory are carved up among resident blocks. A kernel that
uses many registers per thread, or a big slab of shared memory per block, simply
fits fewer warps. Worked example: an SM holds at most 64 warps and 65,536
registers; a kernel using 40 registers per thread needs
One more distinction: effective versus peak bandwidth. Peak is the
datasheet; effective is useful bytes your kernel actually moved per second. They
diverge when warps touch scattered addresses, dragging whole memory transactions across
the bus for a few useful bytes — the coalescing story, previewed here and told in full in
| Measurements say… | Diagnosis | Your move |
|---|---|---|
| achieved bandwidth ≈ peak, flops% low, | memory-bound, at its roof — healthy | raise intensity (tiling, reuse, fusion) or accept victory |
| bandwidth far below peak, still memory-bound | wasted bytes on the bus | fix access patterns — coalescing, layout, smaller types |
| occupancy low, both other numbers low | latency not hidden; the SM idles between dependent ops | cut registers / shared memory per thread, resize blocks |
| flops ≈ peak | compute-bound, at the flat roof | algorithmic change, lower precision, or a bigger GPU |
The whole methodology fits in a dozen lines. Feed it a machine and a kernel's flops and bytes, and it names the wall and the ceiling:
Try your own kernel: count its flops and its DRAM bytes per element, add a line, rerun.
Then try doubling bw (a next-generation memory system) — watch every
memory-bound roof double while the matmul doesn't budge.
The number on the box assumes every FMA unit on the chip issues a fused multiply-add every cycle, forever — no loads, no stores, no dependencies, no divergence, and a kernel that is 100% multiply-adds (an FMA counts as two flops, which conveniently doubles the figure). Peak is not a promise; it is the product of clock frequency and unit count — a statement about what the ALUs cost, not what your program gets. The roofline is the honest translation layer: it converts the box number into your number by asking the one question marketing never does — how many bytes must move per flop? That is also why vendors increasingly quote peak memory bandwidth in the same breath, and why the ratio of the two numbers (the ridge) tells you more about a GPU's personality than either alone. Two chips with identical Tflops but bandwidths a factor of two apart are, for most real kernels, a factor of two apart.
A dashboard shows two kernels: kernel A at 61% of peak flops, kernel B at 4%. Which needs
the engineer? Possibly A. If B is a memory-bound kernel with