AI Infra Interviews logo
← GPU & Accelerator Architecture
Foundational

Roofline Model

Derive a throughput ceiling from work, traffic and hardware limits. Read a measured point below the roof, distinguish memory boundaries, and choose an optimization without promising peak performance.

TL;DR: A roofline is an upper bound on throughput: the smaller of the applicable compute peak and arithmetic intensity times memory bandwidth. It tells you which resource sets the tighter ceiling under your assumptions. A measured kernel can sit well below that ceiling. Name the operation, precision and memory boundary before using the picture to choose an optimization.

A ceiling is a starting point

You time a matrix multiplication, divide its operation count by its runtime, and get a small fraction of the GPU's advertised throughput. Is the kernel inefficient? Perhaps. But first check whether moving its data puts a lower ceiling on the result.

A FLOP is one floating-point operation; FLOP/s is a rate. Arithmetic intensity counts operations per byte transferred across a chosen memory boundary. Here that boundary is HBM, the GPU's large device memory. The GPU Memory Hierarchy explains why reading through a global pointer does not necessarily fetch a byte from HBM.

Let F be the counted floating-point work, D the HBM bytes, P the matching compute peak and B the peak HBM bandwidth:

Intensity I = F / D                          [FLOP/byte]
Compute time floor = F / P                   [seconds]
Memory time floor = D / B                    [seconds]
Total time T ≥ max(F/P, D/B)
Throughput R = F/T ≤ min(P, I × B)

The maximum gives a lower bound on time because computation and transfers can overlap. It does not say they overlap perfectly or exclude other costs. Notice the direction: time is at least the floor, while throughput is at most the ceiling.

Draw one clearly specified roof

Use an SXM (the module that mounts directly on a server board, as opposed to the PCIe card version), dense BF16 tensor-core arithmetic and HBM traffic. From the product specification, use approximately 989 TFLOP/s dense compute and 3.35 TB/s bandwidth. The starred BF16 headline includes structured sparsity; it is not the dense ceiling.

The two ceilings meet at P/B = 989/3.35 ≈ 295 FLOP/byte. This ridge point belongs to the selected compute path and memory boundary. A scalar FP32 loop does not inherit the BF16 tensor-core peak merely because it runs on the same GPU.

Two LLM workloads give the ridge a familiar meaning. Generating one token at a time multiplies each weight matrix by a single vector, about 1 FLOP per weight byte, so its ceiling is 1 × 3.35 = 3.35 TFLOP/s: about 0.34% of the compute peak. Processing a 1,024-token prompt reuses each weight 1,024 times, about 1,024 FLOP per byte, which is right of the ridge. Prefill vs Decode works through that arithmetic.

Throughput (TFLOP/s) H100 SXM · dense BF16 · HBM 11 1010 100100 1k1k ridge ≈ 295 FLOP / HBM byte · log scales Line: ceiling. Dot: example. At I = 10: ceiling 33.5, result 20. The gap is room to investigate.

Both axes use logarithmic spacing: each decade gets equal space. The line is the ceiling, while the dot is an illustrative measurement, not a hardware benchmark. At intensity 10 FLOP/byte:

  • The bandwidth ceiling is 10 × 3.35 = 33.5 TFLOP/s.
  • Suppose measured throughput is 20 TFLOP/s. That is about 60% of the applicable ceiling, although only about 2% of the compute peak.
  • With consistent work and byte counts, R/I = 20/10 = 2 TB/s is the achieved HBM byte rate.

There is room below the roof. Reducing instruction stalls or exposing more concurrent work could improve this kernel without changing its intensity. Being left of the ridge does not prove bandwidth is already saturated.

At intensity 1,000, the formula instead caps throughput at 989 TFLOP/s. It still does not promise that rate: instruction dependencies, on-chip traffic and insufficient parallel work can leave the measured point far below it.

Which bytes went into the division?

A useful estimate and a profiler result can use different byte counts. Make that difference visible rather than treating one as a correction to the other.

CountWhat it answers
Inputs and output, once eachIdeal traffic estimate with explicit cold-data assumptions
Measured HBM trafficBytes that actually crossed the device-memory boundary
Measured L2 trafficA different boundary, requiring its own intensity and bandwidth

Repeated loads can increase actual HBM traffic; cache hits can serve reads without HBM. A warm working set can invalidate a cold-data estimate. If you change the boundary, recalculate I = F/D for that boundary. Do not keep the same x-coordinate by silently changing what “byte” means.

For matrix multiplication, the GEMM guide shows how dimensions determine an ideal work-to-traffic ratio. Implementation details and cache behavior determine how closely that estimate describes an execution. Nsight Compute's roofline documentation distinguishes achieved points from boundaries and provides separate compute paths and memory-level views.

Turn the picture into a test

If measured performance is near the sloped ceiling, reducing HBM traffic is a plausible next experiment. Tiling or Kernel Fusion may preserve reuse on-chip. Batching can share weight reads across more work, but also increases activation traffic and may hurt request latency. Retain the change only if the workload's timing and correctness improve.

If the point is far below the ceiling, inspect the execution first: cache traffic, eligible work, instruction issue and synchronization. If the point is near the compute roof, reducing unnecessary arithmetic may shorten time even when reported FLOP/s falls. Runtime for the required result is the objective; adding dummy arithmetic to move right on a chart helps nobody.

Lower precision needs two separate checks. Storing weights in fewer bytes can reduce traffic. A higher compute peak applies only if the kernel actually uses that arithmetic path. Weight-only quantization with dequantization into BF16 does not automatically gain an FP8 compute roof.

Check your understanding

A kernel has I = 10, with a 33.5 TFLOP/s bandwidth ceiling on the stated H100. You halve HBM bytes while preserving its floating-point work. What follows?

Intensity doubles to 20 and the modeled ceiling doubles to 67 TFLOP/s, still below the compute peak. Measured speed need not double. The transformation might add synchronization or conversion work, or the original execution might have been limited by something else. Recount any new work and measure again.

Key takeaways

  • Use R ≤ min(P, I × B) as a ceiling, and T ≥ max(F/P, D/B) as a time floor.
  • About 295 FLOP/byte is the H100 SXM dense-BF16/HBM ridge, not a universal chip constant.
  • At intensity 10, a 20 TFLOP/s result sits below a 33.5 TFLOP/s ceiling; the gap needs investigation.
  • Keep the work definition and memory boundary consistent. An attractive chart is useful only when it explains a real timing decision.
RELATED CONCEPTS
LESSONS THAT TEACH THIS
PRACTICE THIS IN REAL QUESTIONS