Table of Contents
Roofline model
The roofline model is a visual performance model that tells you whether a kernel is limited by compute throughput or memory bandwidth. It was introduced by Williams, Waterman, and Patterson in 2009. The model gives you a single number to characterize a kernel — its arithmetic intensity — and then plots that against two hardware ceilings to show where the bottleneck is.
Arithmetic intensity (AI) is the ratio of floating-point operations performed to bytes of memory traffic:
$$\text{AI} = \frac{\text{FLOP}}{\text{bytes transferred}}$$
A kernel with high arithmetic intensity reuses data heavily — it does a lot of computation per byte it loads from memory. A kernel with low arithmetic intensity is essentially a data-shuffling operation — it loads data, does a little work, and writes it back.
The two ceilings
Every processor has two relevant hardware limits: a peak compute throughput $\Pi$ (FLOP/s) and a peak memory bandwidth $\beta$ (bytes/s). The attainable performance of any kernel is bounded by both simultaneously:
$$P \leq \min\!\left(\Pi,\ \beta \cdot \text{AI}\right)$$
Plotting this on a log-log graph with arithmetic intensity on the $x$-axis and attainable FLOP/s on the $y$-axis produces the roofline shape: a diagonal line rising with slope $\beta$ (the bandwidth-limited region) that hits a flat ceiling at $\Pi$ (the compute-limited region). The point where the two meet is the ridge point:
$$\text{AI}_{\text{ridge}} = \frac{\Pi}{\beta}$$
A kernel whose arithmetic intensity sits to the left of the ridge point is memory-bandwidth-bound. Adding more FLOP/s to the chip won't help it — you need to reduce memory traffic or increase data reuse. A kernel to the right is compute-bound — memory bandwidth isn't the problem, raw FLOP throughput is.
Two examples
SAXPY ($\mathbf{y} \leftarrow a\mathbf{x} + \mathbf{y}$) does 2 FLOP per iteration and touches 3 floats (read $x_i$, read $y_i$, write $y_i$). For single-precision floats that is 12 bytes per iteration, giving an arithmetic intensity of roughly $\frac{2}{12} \approx 0.17$ FLOP/byte. This puts SAXPY deep in the bandwidth-bound region on essentially any modern processor. Optimizing the FLOP count or vectorizing the loop does almost nothing — the bottleneck is how fast data comes out of memory.
Matrix multiplication (DGEMM) on an $N \times N$ matrix does $2N^3$ FLOP and reads $3N^2$ doubles ($2 \cdot 8N^2$ bytes for inputs, $8N^2$ bytes for output). Arithmetic intensity scales as $\frac{2N^3}{24N^2} = \frac{N}{12}$ FLOP/byte. For large $N$ this grows without bound, pushing matmul well into the compute-bound region. This is why highly optimized BLAS implementations can approach peak FLOP/s on matrix multiply — the hardware is actually the limit.
Using the model
The roofline model is most useful as a diagnostic. Profile a kernel to get its actual FLOP/s, then plot it against the roofline for your hardware. If it sits far below the appropriate ceiling (diagonal for bandwidth-bound, flat for compute-bound), there is optimization headroom. Common fixes for each regime:
- Bandwidth-bound: cache blocking (tiling), loop fusion to increase reuse, reducing unnecessary loads/stores, using smaller data types where precision allows.
- Compute-bound: vectorization (SIMD), increasing instruction-level parallelism, fusing operations to reduce intermediate storage.
Hardware counters via tools like perf or NVIDIA's Nsight are the standard way to measure actual AI on real workloads.
