LLM Compute Planning & Infrastructure

Section 57.1

"Premature optimization is the root of all evil, but failing to plan capacity is the root of all outages."

Adapted from Donald Knuth, Structured Programming, 1974
Big Picture

Compute planning starts before any GPU is rented: it is a sizing exercise driven by your serving SLO, model size, and traffic. This section walks the decisions that turn a chosen model into a hardware bill of materials and a deployment plan that survives real load.

Prerequisites

This section assumes familiarity with LLM API patterns from Section 11.1 and with latency-tail analysis from Section 44.3. The model-registry workflow is covered in detail later in the book.

Compute is the single largest variable cost in an LLM product. Get the planning wrong and you either burn the budget on idle GPUs or run out of capacity at the worst possible moment. This chapter shows how to size compute correctly: which GPUs match which workloads, when API calls are cheaper than self-hosting, how to forecast capacity for production traffic, and how to budget for the unpredictable cost spikes (long-context queries, agentic loops, model upgrades) that wreck plans built on average numbers.

The chapter assumes you have made the build-vs-buy decision from Chapter 63 and are now sizing the "build" side. If you are pure-API, much of this chapter is reference material rather than action items; you still need to understand the GPU tier story to predict your API costs, because providers price relative to their underlying hardware. This section opens with the basic vocabulary and the three workload categories that drive everything else.

57.1.1 The three workload categories

Fun Fact

A 70-billion-parameter model in fp16 needs 140 GB just to load the weights, which means it does not fit on a single H100. Engineers usually discover this on a Friday afternoon, the day before a launch, and the resulting scramble to tensor-parallelize is responsible for a large fraction of all weekend overtime in modern AI startups.

Every LLM compute decision falls into one of three buckets. The categories matter because they have very different cost curves.

Key Insight: Aha Moment: Same Workload, 12x Cost Spread

Take a single concrete task: process 10 million 2,000-token documents through Llama-3-70B for classification. Online inference on Together AI (sub-100ms latency target, on-demand H100s): roughly $4,800 at $0.88 per million tokens, completed in 9 hours. Batch inference on Anthropic's Message Batches API (24-hour SLA, no latency requirement): roughly $2,400 at half-price discount. Training-style scheduled batch on a reserved H100 cluster you own and amortize over 6 months: roughly $400 in incremental GPU-hours because the hardware was already paid for and ran during otherwise-idle nights. Same 20 billion tokens of work, three workload categories, 12x cost spread. The category you choose for a workload often matters more than the model you choose, and most teams discover this only after the third invoice.

57.1.2 GPU tiers in 2026

The 2026 GPU landscape is broader than 2024's. The tiers you actually need to know:

57.1.3 Comparing the GPU options

Table 57.1.1: Production-relevant GPUs, mid-2026.
GPUMemoryBandwidthCloud $/hrBest workload
NVIDIA B200192 GB HBM3e8 TB/s$5-$8Frontier training, big-model inference
NVIDIA H200141 GB HBM3e4.8 TB/s$3-$570B+ inference, mid-scale training
NVIDIA H10080 GB HBM33.3 TB/s$2-$4General-purpose 70B inference
NVIDIA A100 80GB80 GB HBM2e2 TB/s$1-$2Cheap 70B 4-bit, dev / research
NVIDIA L40S48 GB GDDR60.86 TB/s$0.80-$1.507B-13B fp16 inference
AMD MI355X288 GB HBM3e6 TB/s$2-$4Largest-memory workloads
Bar chart of memory bandwidth (TB/s) per cloud GPU in mid-2026: L40S at 0.86
Figure 57.1.1a: Memory bandwidth per cloud GPU at mid-2026 prices. Bars are color-coded by the workload they fit best. For inference the bandwidth bar is what predicts speedup, not the FLOPs the spec sheet leads with. A100 80GB at 2, H100 at 3.3, H200 at 4.8, AMD MI355X at 6, NVIDIA B200 at 8. Bars are color-coded by their workload sweet spot: green for 7B-13B fp16 inference, gold for 70B inference, blue for largest-memory workloads.
Key Insight
Memory bandwidth matters more than FLOPs for inference

An H100 has roughly 2.5x the FLOPs of an A100 but only 1.6x the bandwidth. For inference, the bandwidth ratio is what predicts speedup, not the FLOPs ratio. The same logic flips on training: training is FLOPs-bound, and the H100 / B200's tensor-core advantage is what you are paying for. Match the GPU to the workload: bandwidth-heavy GPUs for inference, FLOPs-heavy GPUs for training. The "Making Deep Learning Go Brrrr" explainer remains the clearest walkthrough.

The 12x cost spread for the same 10M-document Llama-3-70B classification job
Figure 57.1.2: Three ways to push the same 20 billion tokens through Llama-3-70B for a classification task, with a 12x cost spread. Online inference on Together AI's on-demand H100s at $0.88 per million tokens costs about $4,800 and completes in 9 hours; the Anthropic Message Batches API with its 24-hour SLA halves that to $2,400; running the workload as a scheduled job on a reserved H100 cluster amortized over six months drops the incremental GPU-hour cost to about $400. The classification quality is identical across all three. Most teams discover this only after the third invoice; the workload-category decision is what the section recommends locking in before any model choice.

57.1.4 The capacity-planning timeline

Production capacity planning needs a three-horizon view. The thirty-day horizon is "what does my next month look like": traffic forecast, expected model upgrades, planned campaigns. The ninety-day horizon is "what does my next quarter look like": growth trajectory, infrastructure-cost commitments, reserved-capacity discounts. The twelve-month horizon is "what does next year look like": new hardware generations (Blackwell Ultra, Rubin), pricing changes, multi-cloud strategy. Plan for all three; commit only on the thirty-day horizon, hedge on the ninety, and watch on the twelve.

Warning: long-context queries break average-based planning

A 200K-token query costs 200x more compute than a 1K-token query. If your traffic distribution has a long tail of long-context requests (common in document QA, agent loops, code review), the average gives a useless capacity estimate. Plan against p95 and p99 token counts, not the mean. Token-count budgets per request are a useful guardrail; OpenAI Batch and Anthropic prompt-caching discounts can offset, but only if your traffic shape matches the discount terms.

Tip
reserve capacity in 30-day chunks, not in one-year contracts

Frontier-model providers offer aggressive discounts (30-60%) for reserved capacity commitments. The tempting move is to sign a one-year contract for cost certainty. The smarter move in 2026 is 30-day commits: model prices have dropped 50%+ year-over-year for the cheap tier (Gemini Flash, GPT-mini, Claude Haiku), and locking in last year's prices for a year is rarely the right bet. Most providers allow monthly commits without a multi-year contract.

57.1.5 A worked sizing derivation: from model to GPU count

The vocabulary above turns a model into a hardware shopping list only once we can answer the operative question: how many GPUs does a given model at a given traffic level actually need? Section 57.2 develops the full Pareto treatment, but the section would leave the reader stranded if it deferred every number. Here we derive a self-contained estimate from four inputs (model shape, GPU memory, a decode-latency target, and a target QPS) and plug in concrete numbers for one tier so the reader can reproduce the arithmetic.

The derivation has four steps. The first is the per-request memory footprint of the KV cache, which is what actually limits how many requests share a GPU. We reuse the part's KV-cache formula (the same one used for the 70B sizing in Section 57.4 and Exercise 27.14.3): for a context of $T$ tokens,

$$\text{KV}_{\text{req}} = 2 \cdot L \cdot H_{kv} \cdot d_{\text{head}} \cdot T \cdot b$$

where $L$ is the number of layers, $H_{kv}$ the number of key/value heads (under grouped-query attention this is smaller than the number of attention heads), $d_{\text{head}}$ the per-head dimension, $b$ the bytes per element (2 for fp16/bf16), and the leading factor of 2 counts the separate key and value tensors. The second step converts the GPU's free memory into a concurrency ceiling: after the weights are resident, the remaining memory divided by the per-request KV cost gives the maximum number of requests that can be in flight at once,

$$N_{\text{concurrent}} = \left\lfloor \frac{M_{\text{gpu}} - M_{\text{weights}}}{\text{KV}_{\text{req}}} \right\rfloor .$$

The third step turns concurrency into throughput. During autoregressive decode the server emits one token per request per forward pass, and a continuous-batching engine like vLLM runs a batch of $B \le N_{\text{concurrent}}$ requests through each pass in time $t_{\text{step}}$ (the per-token decode latency, memory-bandwidth bound, as established in Chapter 9). A request that emits $G$ output tokens therefore occupies a batch slot for $G \cdot t_{\text{step}}$ seconds, and the per-GPU request throughput is

$$\lambda_{\text{gpu}} = \frac{B}{G \cdot t_{\text{step}}} .$$

The fourth step divides the target traffic by per-GPU throughput and adds headroom, because a GPU planned to 100% utilization has no slack for the long-context tail (Section 57.1.4) or for traffic bursts. With a utilization target $u$ (a headroom factor; $u = 0.7$ leaves 30% slack),

$$N_{\text{gpu}} = \left\lceil \frac{\text{QPS}_{\text{target}}}{u \cdot \lambda_{\text{gpu}}} \right\rceil .$$

Consider one concrete tier: an 8B model (Llama-3.1-8B: $L = 32$ layers, $H_{kv} = 8$ KV heads under GQA, $d_{\text{head}} = 128$) served in bf16 on a single 80 GB H100, at a context of $T = 8{,}000$ tokens, with $G = 256$ output tokens per request and a target of 50 QPS. The weights take $8 \times 10^9 \cdot 2 = 16$ GB. The per-request KV cache is

$$\text{KV}_{\text{req}} = 2 \cdot 32 \cdot 8 \cdot 128 \cdot 8000 \cdot 2 = 1.05 \times 10^9 \ \text{bytes} \approx 0.98 \ \text{GB} .$$

The free memory after weights is $80 - 16 = 64$ GB, so $N_{\text{concurrent}} = \lfloor 64 / 0.98 \rfloor = 65$ requests. Suppose the engine runs a steady decode batch of $B = 48$ (below the ceiling, leaving room for prefill and fragmentation) at a per-token decode latency of $t_{\text{step}} = 18$ ms, a representative bandwidth-bound figure for an 8B model on an H100. Then each request, emitting 256 tokens, holds its slot for $256 \cdot 0.018 = 4.6$ s, and

$$\lambda_{\text{gpu}} = \frac{48}{256 \cdot 0.018} = \frac{48}{4.6} \approx 10.4 \ \text{req/s} .$$

At a utilization target of $u = 0.7$, one H100 sustains $0.7 \cdot 10.4 \approx 7.3$ QPS of usable throughput, so the fleet needs

$$N_{\text{gpu}} = \left\lceil \frac{50}{7.3} \right\rceil = \lceil 6.85 \rceil = 7 \ \text{H100s} .$$

Seven GPUs for 50 QPS of an 8B model at 8K context: the number is dominated by the decode-latency term, not the memory term (the memory ceiling of 65 concurrent requests is never the binding constraint here, because the batch the latency budget allows is far smaller). That is the typical regime for short-to-medium contexts, and it is why Section 57.4 spends its effort on batching and KV-cache reuse rather than on raw memory. The relationship inverts at very long context, where $\text{KV}_{\text{req}}$ grows linearly in $T$ and the concurrency ceiling becomes binding.

Code Fragment 1 packages this derivation as a runnable sizing function so the reader can vary the model shape, context length, and latency target and watch the GPU count move.

# GPU sizing estimate for online LLM serving.
# Chains the four steps from the derivation above:
# KV-cache per request -> concurrency ceiling -> per-GPU throughput -> fleet size.
import math

def gpus_needed(
    params: float,        # model parameter count, e.g. 8e9
    layers: int,          # transformer layers L
    kv_heads: int,        # key/value heads H_kv (GQA-aware)
    head_dim: int,        # per-head dimension d_head
    context: int,         # context length T in tokens
    out_tokens: int,      # generated tokens per request G
    gpu_mem_gb: float,    # GPU memory budget M_gpu
    decode_ms: float,     # per-token decode latency t_step in ms
    batch: int,           # steady decode batch B
    target_qps: float,    # target queries per second
    bytes_per_param: int = 2,  # bf16 weights
    util: float = 0.7,    # headroom factor u
) -> int:
    weights_gb = params * bytes_per_param / 1e9
    kv_req_gb = 2 * layers * kv_heads * head_dim * context * 2 / 1e9
    free_gb = gpu_mem_gb - weights_gb
    n_concurrent = math.floor(free_gb / kv_req_gb)
    eff_batch = min(batch, n_concurrent)  # cannot batch past the memory ceiling
    per_request_s = out_tokens * decode_ms / 1000
    lambda_gpu = eff_batch / per_request_s  # requests per second per GPU
    return math.ceil(target_qps / (util * lambda_gpu))

n = gpus_needed(
    params=8e9, layers=32, kv_heads=8, head_dim=128,
    context=8000, out_tokens=256, gpu_mem_gb=80,
    decode_ms=18, batch=48, target_qps=50,
)
print(f"GPUs needed: {n}")
Output: GPUs needed: 7
Code Fragment 1: A self-contained sizing estimate for the 8B-on-H100 tier worked above. The function chains the four derivation steps and returns 7 for the stated inputs; lowering decode_ms or raising batch drops the count, while raising context eventually makes the memory ceiling (n_concurrent) the binding term. It is a planning estimate, not a load test: Section 57.2 refines it with prefill cost, the latency-throughput Pareto frontier, and measured per-token latency curves.

57.1.6 What comes next

Section 57.2 takes up the sizing math itself in full: given a model, a target latency, and a target QPS, how many GPUs do you actually need once prefill cost and the latency-throughput frontier are accounted for? Sections 46.3 and 46.4 cover the cloud-provider comparison and the breakeven analysis between API and self-hosting that closes Chapter 57.

What's Next

Sizing starts with planning, but the next operational question is how to integrate the compute plan with the rest of your enterprise: data flow, identity, change management. Continue to Section 57.2: Enterprise Integration Patterns for LLM Systems.

Further Reading

Foundational Papers

Pope, R., Douglas, S., Chowdhery, A., et al. (2023). "Efficiently Scaling Transformer Inference." MLSys 2023. arXiv:2211.05102. The most influential paper on inference sizing; introduces the Pareto frontier between latency, throughput, and cost.
Kwon, W., Li, Z., Zhuang, S., et al. (2023). "Efficient Memory Management for Large Language Model Serving with PagedAttention" (vLLM). SOSP 2023. arXiv:2309.06180. Introduces KV-cache paging; the architecture used by all modern inference servers and the basis for tier-by-tier sizing math.

Hardware and Capacity

Patterson, D., Gonzalez, J., Le, Q., et al. (2021). "Carbon Emissions and Large Neural Network Training." arXiv:2104.10350. Methodology for quantifying compute and carbon cost of training runs; underlies any honest hardware-cost analysis.
NVIDIA (2024). "Blackwell Architecture Whitepaper." resources.nvidia.com/en-us-blackwell-architecture. Official spec for B200/B300; the 2026 top-tier hardware.
NVIDIA (2024). "Hopper Architecture Whitepaper (H100/H200)." resources.nvidia.com/en-us-tensor-core. Reference for H100/H200 throughput and memory bandwidth used throughout sizing math.

Surveys

Miao, X., Oliaro, G., Zhang, Z., et al. (2023). "Towards Efficient Generative LLM Serving: A Survey." arXiv:2312.15234. Catalogues efficient-serving techniques that govern capacity planning: continuous batching, paged attention, speculative decoding, quantization.