Skip to content
The Hardware Floor

02.02 · Walkthrough · Free

FLOPs and Bytes

Calculate the FLOP count and memory traffic for a single transformer forward pass. Understand why resource accounting is the first step in any performance investigation.

This video is hosted by Klay so it plays even when YouTube blocks embedding.

Curated for this lesson

The Hardware Floor

CS336 L5: GPUs, TPUs

Segment covering FLOPs and Bytes from Stanford Online.

Transformer inference performance starts with counting floating-point work and memory traffic separately for prefill and decode. Decode is often bandwidth-shaped because weights and KV cache are streamed, while prefill is usually compute-shaped because weights are reused across many tokens. That accounting explains which optimisations can help and which cannot.

What this lesson answers

  • how to count transformer forward pass FLOPs
  • why is LLM decode bandwidth bound
  • prefill versus decode memory traffic transformer

Notes

For one transformer forward pass, the hardware floor is the lower bound obtained by counting required floating-point operations and bytes moved, then comparing them with peak compute and bandwidth: , with arithmetic intensity and ridge point . For autoregressive inference this accounting must be per phase: prefill over prompt tokens has quadratic attention work, while decode for one new token has attention over the existing context and mostly streams weights. A dense decoder block with hidden size , MLP expansion , layers , query heads , KV heads , head dim , and sequence length has approximate prefill FLOPs per layer , where the first term covers QKV/O and gated MLP matmuls and the second covers and . For decode of one token, , but the bytes are often dominated by reading parameters, roughly for FP16 weights if they cannot be reused across a large batch.

Take a Llama-2/3-style 70B dense model in FP16 on one 80GB H100 SXM, with TB/s and FP16 tensor-core peak around TFLOP/s. The raw weight traffic for one decode token is about GB. Even before KV-cache traffic, the bandwidth floor is s, or about tokens/s for batch 1 if every token rereads all weights from HBM. The FLOP count for the same token is about GFLOP for the linear layers, plus attention over context. At TFLOP/s the compute floor is s, so batch-1 decode has arithmetic intensity FLOP/byte, far below the H100 ridge point FLOP/byte. This is why decode throughput engineering starts by increasing effective batch, reusing weights across multiple tokens in flight, and making the KV cache addressable without copying it.

Now include concrete KV bytes, because the “weights dominate” statement stops being enough at long context and grouped-query attention changes the answer. With , , , FP16 KV entries, one cached token stores keys and values of size bytes, about KiB. Decoding at context for one sequence reads roughly GB of KV data if the attention kernel streams all keys and values once. Add that to GB of weights and the bandwidth floor becomes ms, barely different. At , however, KV traffic is GB per generated token, a 30% addition to weight traffic; at batch , weight traffic is still GB per decode step but KV traffic scales with sequences to TB, making attention bandwidth the floor unless the kernel, paging layout, or cache placement changes.

Prefill is accounted differently because weights are reused across tokens and large GEMMs move toward the compute roof. For a 70B model and , the linear-layer FLOPs are approximately TFLOP. The attention FLOPs are material but smaller with : TFLOP, giving about TFLOP total. The compute floor on H100 is s if the whole pass sustained peak, while the one-time weight read floor is still only ms, so optimized prefill is compute-shaped rather than pure HBM-shaped. FlashAttention, from Dao et al. 2022 and FlashAttention-2 in 2023, changes the byte count of attention by tiling Q, K, and V through SRAM and avoiding materialization of the score matrix; it does not change the FLOP term, but it removes the otherwise catastrophic HBM traffic for attention probabilities and makes the above prefill floor plausible.

The named serving systems are best understood as attempts to move an implementation closer to these phase-specific floors, not as magic speedups outside the accounting. vLLM’s PagedAttention paper by Kwon et al. 2023 replaces contiguous KV allocation with page-table-managed blocks, reducing fragmentation and enabling high batch occupancy without copying long caches. SGLang’s runtime and RadixAttention, introduced in the 2024 SGLang paper, exploit prefix sharing so repeated prompts do not repay the same prefill FLOPs and KV writes. TensorRT-LLM’s in-flight batching and paged KV cache releases fuse decode kernels and keep the GEMMs large enough to reuse weights across requests. NVIDIA Dynamo, announced as a disaggregated inference serving stack in 2025, and llm-d, the Kubernetes-native distributed LLM serving project, push the same accounting across machines by separating prefill-heavy and decode-heavy workers and routing KV state explicitly. EAGLE, from Li et al. 2024, attacks the number of target-model decode passes using speculative feature-level drafting; its gain is bounded by the verifier FLOPs and acceptance rate, not by a different transformer cost model.

The floor calculation stops working as a predictor, and some optimizations make things worse, when the counted tensor traffic is no longer the limiting traffic or when batching changes latency constraints. For very small prompts and batch 1, launch overheads, sampling, host scheduling, tokenizer detours, and NCCL collectives can dominate a sub-millisecond kernel floor, so a roofline estimate overstates attainable tokens/s. PagedAttention can hurt when sequences are short and contiguous, because page indirection and non-coalesced KV reads add address-generation and TLB-like overhead without saving meaningful memory. FlashAttention-style kernels can lose to simpler attention for tiny or awkward head dimensions because tiling overhead exceeds the avoided HBM writes. Speculative decoding with EAGLE becomes negative when the acceptance rate is low or the draft/verifier synchronization serializes the path. Disaggregated systems such as Dynamo or llm-d stop helping when KV transfer over PCIe, NVLink, or the network exceeds the saved prefill/decode imbalance; moving a 40 GB long-context cache to avoid milliseconds of compute is bad arithmetic, not an implementation detail.

Common questions

Why count FLOPs and bytes before profiling inference?
The count gives a hardware floor: the best possible time if compute and memory bandwidth were used perfectly. It separates impossible gains from implementation waste. If the byte floor is already larger than the compute floor, kernel tuning for arithmetic will not fix the bottleneck.
Why does decode behave differently from prefill?
Prefill processes a prompt as a large batch of tokens, so matrix multiplies reuse weights and tend to push towards the compute roof. Decode produces one new token per sequence and often rereads model weights and KV cache, so memory bandwidth usually becomes the limiting resource.
When does KV cache traffic matter?
KV traffic grows with context length and with the number of active sequences. For short contexts, parameter reads may dominate decode. At long context or high batch, reading cached keys and values can become the main bandwidth cost, making cache layout and paging decisions performance-critical.