LLM Inference | For You
Lecture 9 of 9

Framework Landscape, Evolution, and New Workloads

The main question of this lecture: after eight lectures of mechanisms, who actually ships all this, how did we get here, and what new workload breaks our two-workload view?

Imagine tomorrow is your first day owning a production LLM deployment. You open the course notes: paged KV, sparse attention, continuous batching, disaggregation, parallelism, kernels, speculative decoding. You can derive each one. Then you open GitHub and meet the names: vLLM, SGLang, TensorRT-LLM, Dynamo, Mooncake. Search "vLLM vs SGLang 2026" and drown in benchmark blog posts. And just as you settle on an engine, the RL team walks over: "we need to swap the model's weights into your serving fleet every ten minutes, and please don't crash." Nothing in your mental model of serving quite covers that.

This final lecture closes exactly those three gaps: who ships it (the framework landscape and how to choose), how we got here (the 2022–2026 evolution and its four main lines), and what breaks next (RL rollout, a workload that is inference but serves nobody). Everything stays anchored to the one ratio you have carried since Lecture 1.

The Spine Revisited: One Formula, Eight Modules

Let us remember our main idea, one last time:

Main idea: the whole course is a set of interventions on the decode arithmetic intensity \[ I \approx \frac{2P\,B}{2P + B \cdot kv} \quad \text{FLOP/byte,} \] where \(P\) is the (activated) parameter count, \(B\) the decode batch size, and \(kv = 2\, n_{layers}\, n_{kv}\, d_h\, b_{dtype}\) the KV bytes per token per request. Decode sustains high goodput only when \(I\) approaches the hardware ridge \(\pi/\beta\) (≈ 295 FLOP/byte on H100). Every module attacks one identified term, or the hardware constants beneath it.
I ≈ 2P · B 2P + B · kv Mod 8 · speculation: τ tokens per weight read speedup ≈ τ / (1 + c_draft): amortizes the 2P read Mods 2 · 3 · shrink and tier kv MLA: 320 → ≈34 KB/token · DSA: read k ≪ L tokens Mods 4 · 5 · keep B pinned at the ceiling continuous batching · chunked prefill · PD disaggregation Mods 1 · 6 · 7 · the ground truth measure honestly (MFU/MBU/goodput) · split 2P + B·kv across GPUs · drive π and β toward their peaks one ratio; eight interventions; every mechanism you know is in one of these boxes
How to: start at the fraction in the middle; each dashed arrow attaches the modules that act on that term. If a serving problem is slow, find which term dominates at your operating point. Then the arrow tells you which module to reach for.

Three structural remarks, because they are the difference between knowing the mechanisms and wielding them:

  1. The interventions compose multiplicatively. Paging enlarges the feasible region of \(B\), scheduling fills it, sparsity and MLA shrink the cost of filling it, parallelism splits what remains, kernels make the hardware deliver its peak, and speculation changes what "one step" produces.
  2. They are ordered by leverage. At low \(B\), the \(2P\) weight-read term dominates, and only batching, parallelism, and speculation help. At high \(B\) and long \(L\), the \(B \cdot kv\) term dominates, and KV compression and sparsity become the binding constraint. That is exactly why Modules 2 and 3 sit at the center of this course.
  3. The model itself is a knob. MLA and DSA act on \(kv\) directly, and MTP acts on the speculative \(\tau\). The architecture is a dial on the same formula. Keep that thought; it is the seed of the co-design argument below.
Engineering Takeaway: when a serving deployment underperforms, do not profile blindly. Compute the operating point \((B, L)\), evaluate both terms of the denominator \(2P + B \cdot kv\), and identify which module's mechanism addresses the dominating term. A prefill-heavy, cache-poor workload needs Module 2's reuse, not Module 7's kernel tuning; a decode-bound long-context workload needs Modules 3/5, not more tensor parallelism.

The Framework Landscape: Four Systems on a Converging Checklist

Fine, the mechanisms are yours. Now somebody has to press the deploy button. The mechanisms do not exist in the abstract; they live inside a small number of production engines, and the honest way to picture them is not a league table but a map: each system has a hallmark, a thing it does more natively than anyone else.

scope: one engine instance → the whole cluster depth for a chosen target → breadth you stop optimizing inside an instance here vLLM hallmark: breadth · PagedAttention origin NVIDIA · AMD · TPU · day-0 models SGLang hallmark: depth · RadixAttention origin frontier MoE form · day-0 sparse attn TensorRT-LLM hallmark: kernel & compilation depth (new NVIDIA silicon first) Dynamo not an engine: orchestration above engines · routing, queues, KVBM, NIXL Mooncake KVCache-centric cluster store, PD disaggregation industrialized ...can all be workers under the orchestrator
How to: read left to right first. Everything left of the dashed line is a single engine instance; right of it lives the layer that schedules across instances and treats their KV as one pool. Then read top to bottom: vLLM's commitment is breadth, and the two below it trade breadth for depth in a chosen target (frontier models for SGLang, NVIDIA silicon for TensorRT-LLM).

Walking the map slowly, system by system:

Here is the layer-by-layer checklist, with the course mechanism behind each cell. Read the last two rows carefully, because they are the punchline:

LayervLLMSGLangTensorRT-LLMDynamo (orchestration)
KV management (M2)PagedAttention (origin)Paged + RadixAttention (origin)Paged KVKVBM: tiered block storage, cache-aware routing
Prefix reuse (M2)Block hash chainRadix treeSupportedRouting layer assigns by overlap score
Scheduling (M4)Continuous batching, chunked prefill, async schedulingZero-overhead overlap schedulerIn-flight batchingGlobal prefill queue, xPyD conditional disaggregation
Parallelism (M6)TP / PP / EP / DP / DCPTP / PP / large EP (DeepSeek's form)TP / PP / EPCross-instance orchestration and scaling
Kernels (M7)Pluggable attention backendsFlashInfer / FlashMLA, dual page sizeIn-house kernels, Blackwell-first(NIXL transfer layer instead)
PD disaggregation (M5)SupportedSupportedSupportedGlobal scheduling, conditional disaggregation
Speculative decoding (M8)EAGLE/Medusa-style, MTPEAGLE-2/3, MTPMedusa/EAGLE-style(delegated to engines)
Sparse attention (M3)Backend-dependentDay-0 V3.2 DSABackend/compiler-dependentn/a

Everything on the checklist exists everywhere. Speculation and sparse attention are no longer differentiators in kind, only in maturity and defaults.

This leads to the lecture's two observations. Honestly, they reframe what "choosing an engine" even means:

Observation 1: single-engine checklists have converged. Every technique in this course exists in all three engines. What remains: maturity (whose overlap scheduler actually hides CPU time under load), defaults (which backend and chunk size you get out of the box), and ecosystem (hardware and model coverage, surrounding tooling). Choosing by feature presence is almost always a mistake.
Observation 2: the center of competition is moving outside the engine. The remaining large gains are in multi-instance orchestration, shared tiered KV pools, and cache-aware routing; Dynamo and Mooncake mark the shift. In the language of the spine formula: within one instance, \(B\) and \(kv\) are close to their local optima; the open frontier is letting \(B\) and the KV pool span a whole cluster without losing locality.
? If every engine has every feature, what could a benchmark post titled "engine X is 2× faster than engine Y" even be measuring? Think about Lecture 1's metrics discipline before opening.

Possible answer

Almost never a mechanism. Usually it measures a default or a maturity gap at a specific operating point: an engine whose default is colocated prefill looks terrible on chat until you enable chunked prefill or disaggregation; one overlap scheduler may hide CPU time better at your \(B\); one prefix-cache implementation may degrade better at your hit-rate distribution. Defaults are load-bearing: compare tuned configurations on your traffic replay, or the number says nothing transferable. (This is pitfall #1 at the end of the lecture, already in the wild.)

TA says: want the theory stress-tested? Watch what the 2026 frontier releases actually did. When Kimi K3 dropped (weights on 2026-07-27), vLLM upstreamed the entire serving stack on day 0 in v0.27.0 (hybrid KDA-state + paged-MLA cache management, fused FlashKDA / AttnRes / LatentMoE kernels, native MXFP4 MoE, DSpark speculation, PD disaggregation over NIXL), shipped as Docker images on the CUDA 13.0 stack, validated floor 8×B300 (16×B200 or 8×MI355X alternates); v0.28.0 followed with decode context parallelism, fused FlashKDA decode, ROCm, and EAGLE3-on-KimiLinear. SGLang matched day-0 and published official K3 and GLM-5.3-Flash cookbooks (ReplaySSM for speculation on the linear state, unified-pool KDA/MLA caches). TensorRT-LLM? No native K3 or GLM-5.3 support. The NVIDIA-sanctioned path is Dynamo recipes on GB200/GB300: the first clear instance of an orchestration layer, not an engine, deciding frontier-model coverage. New entrant to track: TokenSpeed is on Moonshot's recommended-serving list for K3. And GLM-5.3-Flash needs vLLM 0.29.0+ (sparse-MLA kernels are Hopper-or-newer) with SGLang day-0. For 2026 hybrid models, one question dominates the model-family axis: which engine has the state-management path upstreamed? Hybrid caches and rollback are too intricate to bolt on locally.

Which Framework When: Four Axes, Not a Checklist

Because the checklists converge, selection reduces to four axes: workload type, model family, hardware, team constraints. The decision guide compresses to a table you can interrogate:

Axis / scenarioStarting pointWhy
Heterogeneous hardware (NVIDIA + AMD + TPU), many model familiesvLLMBroadest backend matrix; pluggable attention per platform
New open-weight model released this morningvLLM or SGLangBoth hold a day-0 convention; check which merged support first for that family
DeepSeek family (V3/V3.2/R1) at scale, large EP + PDSGLangReproduces the official deployment form; day-0 DSA; dual page size
Structured-output heavy (agents, JSON-mode APIs)SGLangCompiled constrained decoding in the serving path
Brand-new NVIDIA silicon (Blackwell bring-up)TensorRT-LLMFirst-day kernels and quantization appear here first
Multi-node cluster, PD pools, KV tiers, cache-aware routingDynamo over whichever engine(s)Orchestration is the product; engines are workers
RL post-training rollout fleetvLLM or SGLang embedded in verlBoth expose weight hot-update; verify partial-rollout at your trajectory lengths
Small team, one model, one GPU generation, minimal opsAny single engine, colocated PDOrchestration overhead buys nothing below Module 5's disaggregation threshold
Two cautions on using the table: (1) Defaults are load-bearing: compare tuned configurations, never out-of-box ones. (2) The axes interact: "DeepSeek on Blackwell" pits SGLang's model depth against TensorRT-LLM's hardware depth, and the honest answer is a benchmark on your traffic, or both engines under one orchestrator.
Worked example (framework selection end-to-end, do it with me): A provider must serve DeepSeek-V3.2 (MLA + DSA, 256+1 routed experts, MTP) on a 64-node H800 cluster; traffic is 70% multi-turn agentic sessions with heavy shared system prompts (expected prefix hit \(h \approx 0.8\)), p95 TTFT SLO 2 s at 128K context; the team also runs weekly RL post-training.
Step 1 (model family): V3.2's production form is large EP + PD with DSA day-0 in SGLang; the alternative is re-implementing dual-page-size DSA cache management yourself. → SGLang.
Step 2 (workload): at \(h = 0.8\), effective prefill FLOPs drop to \((1-h)\,2PL = 0.2\,2PL\). Radix-tree reuse is not optional; it is a 5× prefill-cost lever. Cluster-level cache-aware routing then decides which worker realizes the hit.
Step 3 (cluster): 64 nodes with a TTFT SLO under load implies independent prefill/decode pools (Module 5's interference argument), a global prefill queue, and KV-aware routing → Dynamo above the SGLang workers, KVBM tiering the 128K-context KV (≈4.4 GB per request even with MLA) across HBM/DRAM.
Step 4 (RL): embed the same engine under verl with weight hot-update, reusing the production stack so rollout numerics match serving numerics.
Decision: Dynamo + SGLang + verl-embedded rollout; re-evaluate TensorRT-LLM workers only if the fleet moves to newer NVIDIA silicon. Every arrow traces to a numbered module. That is the point of the course.
Engineering Takeaway: evaluate engines on your own traffic replay, not feature matrices. The cells are all "yes" by now; what differs is tail latency under your prefix-hit distribution, your model, your hardware. And expect the next procurement question to be about the orchestration layer, not the engine.

The Evolution Timeline: Four Main Lines

Now the second gap: how did we get here? Line up 2022–2026 and, surprisingly, a plot appears. The field keeps attacking whichever term of the spine formula was binding at the time:

2022 → 2026 · colored by which line of evolution each milestone belongs to 2022 · FasterTransformer hand-fused kernels, static batching 2022 · Orca continuous batching: quantum → the step 2023 · vLLM PagedAttention: KV becomes allocatable 2023–24 · SGLang · Sarathi RadixAttention: KV becomes reusable chunked prefill: quantum → token budget (Sarathi is also Line 1) 2024 · Mooncake PD disaggregation industrialized; KVCache-centric tiered storage 2025 · DeepSeek week FlashMLA · DeepEP · DeepGEMM: co-design goes public 2025 · Dynamo orchestration above engines · NIXL 2025 · V3.2 DSA · DFlash sparse attention and parallel drafting hit production 2025 late · Kimi Linear / KDA fixed recurrent state replaces growing KV (3:1 hybrid) 2026 · full-stack co-design DeepSeek V4 (CSA/HCA) · Kimi K3 GLM-5.3 (-Flash) · DSpark · ReplaySSM · TreeWY: model + kernels + parallelism + RL infra as one release Line 1 · finer scheduling granularity Line 2 · memory becomes a managed resource Line 3 · deployment decoupling Line 4 · model–system co-design
How to: read the milestones left to right, then re-read column by color. The ordering (kernels → scheduling → memory → reuse → disaggregation → co-design → orchestration) is not historical accident; it is the intensity formula's binding term, moving year by year.

Each line deserves one paragraph of "what changed / why it matters / what comes next":

Line 1, scheduling granularity: the decision quantum went request (FasterTransformer's static batches) → step (Orca, 2022) → token budget (Sarathi, 2023–24). Each refinement put the decision closer to where cost is incurred, keeping \(B\) pinned at the ceiling; token budgets let prefill and decode coexist in one step without the GEMM monopolizing the device. Next: elastic scheduling for loads that fluctuate an order of magnitude within a step (RL rollout and agentic traffic), with requests that must be interruptible, not merely preemptible.
Line 2, memory becomes a managed resource: watch the KV cache's career: an execution detail inside the attention kernel (2022) → a paged, allocatable resource (vLLM, 2023) → a reusable asset shared across requests (radix trees, 2023–24) → a tiered, routable, cluster-scale asset (Mooncake 2024; Dynamo KVBM + routing 2025). Paging removed the fragmentation tax; reuse gave the \((1-h)\) free-prefill lever; tiering acknowledged KV working sets exceed HBM (DRAM/NVMe/remote at 25–50 GB/s RDMA hold the cold part); routing made locality a scheduling signal. Next: KV as the cluster data structure: cross-engine cache formats, session-spanning KV, lifecycle for interrupted trajectories.
Line 3, deployment decoupling: single colocated instance → PD disaggregation (industrialized by Mooncake, 2024) → multi-pool orchestration with independent scaling, global queues, and conditional per-request disaggregation (Dynamo, 2025). Prefill is a GEMM workload, decode a GEMV one; colocating them means decode's TPOT SLO loses. Decoupling lets each phase sit at its own roofline corner with its own parallelism and replica count, and lets the pools scale independently as the prefill:decode cost ratio shifts with traffic mix and hit rate. Next: conditional disaggregation as default; NIXL toward NVLink-domain speeds across nodes; orchestration that counts the training cluster as a peer.
Line 4, model–system co-design (the new differentiator): the model side started making architecture decisions for system goals. MLA compresses \(kv\) by ≈10× (320 KB → ≈34 KB/token); DSA turns attention from \(O(L)\) to \(O(k)\) reads per step with a 132 B/token indexer; MTP builds speculative capability into the checkpoint itself (85–90% second-token acceptance); DeepSeek's open-source week published the matching kernels and large-EP deployment form. The first three lines are converging: everyone pages, everyone reuses prefixes, everyone disaggregates. And converged lines stop differentiating. Co-design is non-convergent and compounding: the ceiling of what systems can achieve is increasingly decided at training time, in the KV footprint the architecture commits to, the attention operator it selects, the speculative heads it ships.
Worked example (the cache trajectory in one line of arithmetic): follow per-token cache bytes, BF16, across the course's canonical models: \[ 320\ \text{KiB} \xrightarrow{\;\times 1/9.4\;} 34\ \text{KiB} \xrightarrow{\;\times 1/1.26\;} 27\ \text{KiB} \xrightarrow{\;\times 1/2.3\;} 11.7\ \text{KiB} \] GQA-70B baseline (320 KiB → 320 GiB at 1M context, infeasible single-tenant) → DeepSeek-V3 MLA (9.4×) → Kimi K3 hybrid (27 KiB on the 24 MLA layers + a fixed 0.2 GiB KDA state ⇒ ≈27.2 GiB at 1M, ≈11.8× under the GQA baseline; the state term stops scaling with \(L\) entirely) → GLM-5.3-Flash (≈0.26 KB/token/layer averaged over 45 layers vs 1.15 KB for GLM-5.3's MLA) ⇒ ≈11.7 KiB/token, ≈27× below GQA. Cumulatively, a 320 GiB per-request 1M-context working set becomes ≈12 GiB. And look at where every factor came from: a training-time decision. Latent compression (M2), fixed recurrent state (KDA), selection sparsity (M3).
Note (read vendor numbers like an engineer): the last factor mixes units deliberately: 0.26 KB is a per-layer average over a hybrid stack (34 fixed-state KDA layers + 11 sparse-MLA layers); multiplying by 45 layers is what makes it comparable to the per-token figures. Always check which basis a cache number is quoted on. And keep one eye on the dissenter: MiniMax M2/M3 dropped its linear layers after failed ablations. The 2026 convergence on "hybrid linear + sparse/compressed full attention + built-in speculation" (Qwen3-Next 3:1 GDN + MTP; K3 69 KDA : 24 Gated-MLA + DSpark; GLM-5.3-Flash 34 KDA + 11 sparse-MLA + a shipped MTP layer; DeepSeek V4 CSA/HCA) is empirical, not a theorem. Dissenters are where a template's boundary conditions will surface.
Engineering Takeaway: track all four lines when capacity-planning, but weight line 4 in model selection. Two checkpoints with equal benchmark quality can differ by an order of magnitude in serving cost purely through \(kv\) and attention structure. Evaluating a model without computing its \(kv\)/token and attention complexity is, after this course, an unforced error.

RL Rollout: The Third Workload

Now for the twist that breaks the frame. Since Lecture 1, we have classified traffic into two workload classes: latency-sensitive online serving (SLO-bound, goodput-defined) and throughput-bound offline batch. RL post-training adds a third. In frameworks like verl, the training loop alternates optimizer steps with rollout: the current policy generates samples (responses or full agentic trajectories) which the trainer then learns from. Rollout is inference (mainstream stacks embed vLLM or SGLang as the rollout engine), but it obeys neither class:

Trainer optimizer step, T minutes P params sharded over G GPUs scores: π_train (training kernels) Rollout engine (vLLM / SGLang) no SLO: B pinned at the memory ceiling logprobs: π_rollout (inference kernels) suspend → pin KV → swap weights → resume (while sync runs, these GPUs idle, and the training step stretches as if the trainer were slower) weight sync: must fit ε · T G·β_net ≥ P·b_dtype / (ε·T) samples → learn · ratio ρ = π_train / π_rollout watchdog: per-token logprob gap δ̄; bias ≠ noise! Environment fleet (AgentEnv, 2026) Firecracker microVMs · 133 ms checkpoint / 49 ms resume decouples env lifetime from trajectory and weights the load shape: bursts, not a stream tool-call-interleaved generation; environments return in waves ⇒ B swings ×10 within a step; prefix hits near the high-h regime
How to: trace one training step clockwise. Red arrow: new weights must cross in a fraction ε of step time T; idle rollout GPUs are wasted trainer time. Green box: rollout is inference with the latency constraints removed and four new ones added. Blue arrow: samples and their likelihood ratio ρ flow back, and a per-token numerical gap compounds across the whole trajectory. Amber box: the 2026 addition, snapshotting environments instead of idling through their waits.

Weight Sync: A Time-Budget Model

After every training step (a cadence of minutes or shorter) the updated weights must reach the rollout engine, in seconds. How much bandwidth does that need? Let's count. Let the trainer hold \(P\) parameters at \(b_{dtype}\) bytes/element, sharded across \(G\) training GPUs each with inter-node egress \(\beta_{net}\) (≈ 50 GB/s per GPU on 400 Gbps IB/RoCE). If the transfer must finish within a fraction \(\epsilon\) of step time \(T\): \[ \underbrace{\frac{P \cdot b_{dtype}}{G \cdot \beta_{net}}}_{\text{broadcast time (tree/pipelined)}} \;\le\; \epsilon\, T \qquad\Longrightarrow\qquad G\cdot\beta_{net} \;\ge\; \frac{P\cdot b_{dtype}}{\epsilon\, T}. \] The model assumes trainer shards stream in parallel (each sends its own \(P/G\) shard) with a pipelined broadcast, per-GPU egress being the bottleneck: the standard NCCL/RDMA weight-broadcast form.

Worked example (sizing sync for a 671B MoE): DeepSeek-V3 scale: \(P = 671\)B full checkpoint in BF16 (the system must move all of it, not just the 37B activated): \(P\,b_{dtype} = 1.34\) TB. Step \(T = 10\) min \(= 600\) s; budget \(\epsilon = 2\%\) → sync must finish in 12 s.
Required bandwidth: \(1.34\ \text{TB} / 12\ \text{s} \approx 112\) GB/s → as few as 3 sending GPUs suffice; a 64-GPU trainer pushing in parallel finishes in \(1.34\ \text{TB}/(64 \cdot 50\ \text{GB/s}) \approx 0.42\) s. FP8 checkpoint (671 GB): all times halve. Dtype is a first-class sync lever.
Colocate alternative (train + rollout share GPUs): an in-memory/NVLink-domain swap. 1.34 TB at NVLink ≈ 900 GB/s ≈ 1.5 s; at HBM copy speeds ≈ 0.4 s. Over PCIe alone (64 GB/s): ≈ 21 s, already over budget; this is why colocate designs stage weights through NVLink/HBM paths, never PCIe.
Sanity check (limits): a 2-minute step at the same 2% budget needs 5× the bandwidth: 560 GB/s, i.e. ≈12 senders, or FP8 + 6 senders. Short-step RL is exactly where weight sync stops being free.
Note: the structural requirement underneath the budget is an efficient weight hot-update path: pause generation, swap tensors in place (ideally zero-copy from an NCCL receive buffer or shared memory), resume. Traditional serving never had this interface, because serving weights are immutable for the process lifetime.

Colocate vs a dedicated rollout fleet mirrors Module 5's disaggregation logic, one level up. Each earns its keep at a different scale:

DimensionColocate (train + rollout, same GPUs)Disaggregated (dedicated rollout fleet)
Weight syncIn-memory / NVLink-domain swap; sub-second to ~1.5 sNCCL/RDMA broadcast; the budget governs; typically 0.4–3 s at \(G \ge 16\)
GPU utilizationTime-sliced: both alternate on the same devices; no idle fleetRollout GPUs idle during the optimizer step unless steps are pipelined
Memory pressureOptimizer + gradients + activations and KV pages must fit; M2's tiering becomes survivalEach side sized for its own working set
Engine integrationIn-process; hot-update is a pointer/tensor swapEngine as a service; hot-update is remote + broadcast
Failure / isolationA training crash kills rollout and vice versaIndependent scaling and fault domains
Best whenSingle mid-size cluster, long optimizer steps relative to rolloutLarge clusters, short steps, or rollout fleets doubling as serving capacity

As scale grows, the disaggregated form wins on utilization and isolation, and the weight broadcast becomes a first-class distributed-systems problem: tree topology, pipelining, FP8 quantization of the update, overlapping sync with the tail of the previous rollout.

Partial Rollout and the δ̄ Watchdog

Agentic trajectories reach hundreds of thousands of tokens, far longer than one training step's rollout window. If every trajectory must finish on one weight version, two failure modes follow: the long-tail stall (the slowest trajectory gates the whole step; utilization collapses while 99% of GPUs wait), and unbounded off-policy drift (the policy that wrote a long trajectory's early tokens is many updates old by the end). Partial rollout answers both: at a sync boundary, interrupt in-flight trajectories, keep their KV, swap weights, resume. Three requirements land squarely on Modules 2 and 4:

  1. An interruptible request lifecycle. A suspend state distinct from running and from preempted-to-recompute: generation stops at a token boundary, but the request's KV blocks are pinned, not freed. Stronger than Module 4's preemption, which trades KV away for memory.
  2. KV lifecycle across weight versions. Keep or recompute? An algorithmic decision exposed to the trainer.
  3. Fairness under suspension. Suspended trajectories resume ahead of fresh requests if tail completion matters, behind them if throughput does. It is a scheduling knob with direct consequences for sample efficiency.
? The prefix's K/V were computed by the old weights. Lecture 1 proved the KV cache is legal by causality. So is keeping the pinned KV after the weight swap still "exact"? Recall what the proof assumed before you open.

Possible answer

Causality guarantees that later tokens never change earlier activations. But the cached K/V are still functions of the weights that produced them. Recomputed-equivalent K/V of the prefix require a re-prefill under the new weights. So engines choose: accept the mixed-version KV as an off-policy price (the trajectory's prefix was genuinely generated by an older policy), or selectively re-prefill. Either way it is an algorithmic trade-off the trainer must know about, not something the engine can silently decide.

Conservative reading: the source text is terse here, but this matches its phrasing: "cached K/V of the prefix are recomputed-equivalent only if we re-prefill under the new weights; engines either accept the mixed-version KV as the off-policy price, or selectively re-prefill."

Now the subtlest constraint, and my candidate for "easiest way to silently break an RL stack." On-policy corrections assume generation probabilities are known exactly. The importance-sampling ratio for a token (multiplied, a trajectory): \[ \rho = \frac{\pi_{train}(a_t \mid s_t)}{\pi_{rollout}(a_t \mid s_t)}, \qquad \log \rho_{traj} = \sum_{t=1}^{N}\left(\log \pi_{train} - \log \pi_{rollout}\right)_t. \] The catch: rollout logprobs come from inference kernels (fused, reassociated, possibly FP8/TF32, speculative-verified) while training logprobs come from training kernels, with different reduction orders and different dtypes. Floating-point addition is non-associative, so the same sequence scores differently by small per-token gaps \(\delta_t = (\log\pi_{train} - \log\pi_{rollout})_t\) even at identical weights, and the ratio picks up the factor \(\exp\bigl(\sum_t \delta_t\bigr)\). How bad that factor gets depends entirely on the structure of \(\delta_t\):

Worked numbers, three regimes (pin these to your wall):

Same magnitude, three fates. The operative question is never whether \(\delta_t\) is small (it always is) but whether it is biased. Mitigations fall straight out of the algebra: align reduction orders and dtypes in the logprob path (the sampling path can stay fast); keep per-token ratios so clipping absorbs local spikes; and measure \(\bar\delta\) on held-out sequences after every kernel or engine upgrade. It is a one-line regression test with \(10^4\)-token compounding consequences.

TA says: the 2026 instance is Kimi K3 again; it made rollout infrastructure itself a published system. AgentEnv runs agentic environments in Firecracker microVMs with 133 ms checkpoint / 49 ms resume, and exercised 51.2M sandboxes over K3's training: the environment-side counterpart of partial rollout (engine suspends trajectories; AgentEnv freezes the environments themselves at 49-ms granularity instead of idling GPUs through tool waits). Rollout is now a three-layer stack (engine, orchestration, environment fleet), each layer with its own checkpoint/resume machinery. And day-0 LoRA RL on native MXFP4 weights (SGLang + Miles): the weight-sync \(P\,b_{dtype}\) term drops from a ~1.56 TB checkpoint to adapter-sized, so the broadcast budget stops binding at short steps. Meanwhile the numerics gap gains a new term (MXFP4 expert GEMMs vs higher-precision training logprobs), making δ̄ monitoring mandatory from step one.

Engineering Takeaway: three rollout rules. (1) Budget weight sync with the feasibility inequality before choosing colocate vs disaggregated; if the required aggregate bandwidth exceeds your fabric, the decision is made for you. (2) Demand a real weight hot-update path and a suspend-and-pin-KV scheduler state; retrofitting either into a serving-only engine is a research project. (3) Treat \(\bar\delta\) as a monitored SLO of the RL stack: \(10^{-4}\) per token is a 2.7× trajectory-ratio distortion at 10K tokens; you cannot clip your way out of bias. And when evaluating a 2026-class model for RL, ask for three artifacts with the weights: the rollout-engine integration, the environment infrastructure, and the quantized-native training path with a measured \(\bar\delta\). A model that ships all three has pre-paid the rollout engineering.

The epilogue is the familiar pattern of the timeline: the features RL rollout forced into existence (hot-update interfaces, interruptible lifecycles, coexistence with training frameworks) are now official feature areas of both vLLM and SGLang, not forks. A workload pressure appears, one system answers it, the answer becomes checklist. Whatever workload class follows agentic RL will arrive the same way: as new constraints on these same layers.

Common Pitfalls

Six misconceptions to lose before you graduate:
  1. Choosing an engine on the feature checklist alone. Everything in this course exists in all three engines; decide on maturity, defaults, ecosystem, and measured behavior on your traffic.
  2. Ignoring ecosystem and maturity asymmetries. "Supports large EP" and "reproduces DeepSeek's official deployment form in production" are different claims: a feature vs an operational track record.
  3. Treating RL rollout as ordinary offline serving. Max batch, static weights, no hot-update silently breaks the training loop's assumptions.
  4. Ignoring numerical consistency. A per-token gap of \(10^{-3}\) looks like floating-point noise... until it compounds into a 22,000× ratio distortion over 10K tokens. Measure the bias, not the magnitude.
  5. Over-orchestrating small deployments. Below Module 5's disaggregation threshold, a global queue and KV routing add failure modes without adding throughput.
  6. Evaluating models without their system signature. Equal-quality checkpoints can differ ≈10× in serving cost via \(kv\) and attention structure alone. Architecture is a serving-cost parameter.

Research Thinking

How to: read the starting point; read the question and think, for a minute, a day, a week... and only then open the answers. You are not supposed to reinvent several months of someone's research; it's the habit of thinking that counts.

? Card 1, "invent" the weight-sync budget. Starting point: rollout GPUs idle during weight sync stretch the training step exactly as if the trainer were slower. Question: your trainer runs 2-minute steps on a 671B model (BF16, 1.34 TB) with G = 32 GPUs at 50 GB/s each. What fraction of the step does sync consume, and what would you demand for \(\epsilon \le 1\%\)? Compute before opening.

Possible answer

Broadcast time \(= P\,b_{dtype}/(G\beta_{net}) = 1.34\ \text{TB}/(32 \cdot 50\ \text{GB/s}) = 0.84\) s → \(\epsilon = 0.84/120 \approx 0.7\%\): already under 1%. The \(\epsilon \le 1\%\) requirement asks \(G\beta_{net} \ge 1.34\ \text{TB}/(0.01 \cdot 120\ \text{s}) = 1.12\) TB/s, i.e. 23 senders at 50 GB/s; the 32-GPU trainer (1.6 TB/s aggregate) meets it with margin. With only 8 GPUs (400 GB/s) it fails. Then the levers are: FP8 the checkpoint (halves the bytes); pipeline the sync, overlapping it with the tail of the previous rollout; or go colocate and stage through NVLink/HBM. The 2026 radical answer: sync adapters. LoRA-on-MXFP4 drops \(P b_{dtype}\) from ~1.56 TB to adapter size, and the budget stops binding at any realistic step time.

Existing attempts: pipelined NCCL/RDMA tree broadcast (verl-class stacks), FP8 quantization of the update itself, colocate NVLink-domain swaps, and the SGLang + Miles quantized-native LoRA path.

? Card 2, bias is not noise. Starting point: \(\log\rho_{traj} = \sum_t (\log\pi_{train} - \log\pi_{rollout})_t\) and the two stacks disagree by \(\sim 10^{-3}\) per token no matter what you do. Question: why does a systematic gap of \(10^{-3}\) destroy the learner while an i.i.d. gap of the same size is fine? And which single regression test distinguishes them after every engine upgrade? Derive both cases before opening.

Possible answer

Systematic: errors add. \(\sum_t\delta_t = N\bar\delta\), linear in trajectory length: \(N{=}10^4\), \(\bar\delta=10^{-3}\) ⇒ ratio off by \(e^{10} \approx 22{,}000\times\); clipping just saturates and hides it. I.i.d.: errors add in quadrature. The log-ratio std grows as \(\sigma_\delta\sqrt{N} = 0.1\), an 11% wobble: tolerable. Same per-token magnitude, \(22{,}000\times\) vs \(1.11\times\), separated only by \(E[\delta_t]\). The test: score a held-out batch of sequences in both stacks after every kernel/engine/dtype upgrade and estimate \(\bar\delta\) (a mean, not a magnitude). One line of code, \(10^4\)-token consequences. Bonus: per-token ratios let clipping absorb local spikes before they compound.

? Card 3, predict the stack before you check it. Starting point: the four selection axes (workload, model family, hardware, team). Scenario: a startup serves Llama-3.3-70B chat plus a growing set of open-weight models on a mixed fleet (H100 today, AMD MI300X next quarter, TPU spot under evaluation); single-turn traffic with modest prefix overlap (\(h \approx 0.2\)); 4 nodes now, 12 planned; two infra engineers. Question: what stack would you recommend, layer by layer? And which single change would flip the answer?

Possible answer (and how it flips)

Model family: "many models" → the breadth axis dominates → vLLM (widest hardware matrix, day-0 support). Workload: \(h \approx 0.2\) makes prefix reuse a minor lever (single-turn traffic pays \((1-h)\,2PL = 0.8\,2PL\)), so SGLang's radix depth is not decisive. Hardware: mixed fleet again points to vLLM; TensorRT-LLM would strand the AMD/TPU capacity. Scale/team: at 4–12 nodes of single-phase chat, disaggregation is marginal (Module 5's threshold), and Dynamo buys two engineers orchestration overhead, not throughput. Stack: vLLM, colocated with chunked prefill; defer orchestration. The flip: "DeepSeek-V3.2 at 64 nodes" moves every axis toward SGLang + Dynamo: exactly the worked example above. Same axes, opposite corner.

Have Fun! The Weight-Sync Budget Calculator

Enough reading. Now you sign off on the sync budget. Set the checkpoint, the trainer size, and the step cadence, and watch the budget bind. Can you find the smallest sender count that keeps a 2-minute step inside 1%? And at what step cadence does any BF16 broadcast fail no matter how many GPUs you throw at it... until you flip to FP8?



Budget physics: feasibility lives and dies by \(G\beta_{net} \ge P\,b_{dtype}/(\epsilon T)\). And dtype is a first-class lever, not a detail.

Seminar & Homework

Lab 9: Framework Comparison and RL-Rollout Reading closes the hands-on pack with two halves, mirroring the lecture:

Summary

← Lecture 8: MTP and Speculative Decoding Back to the course map →