Chapter 07 · Scale

Scaling RL: infrastructure, environments, agents

An RL step often spends most of its time waiting for the slowest rollout. Most of RL's surprises come from the gap between the model you sample from and the model you train. Most of its failures come from the environment, not the algorithm. This chapter covers all three.

⏱ 80 min9 interactivesPrereq: ch. 02 (importance sampling, PPO) · ch. 06 (GRPO family)
In one breath
  • Generation usually dominates. Published profiles put rollouts at roughly 60–90% of iteration time, and a long tail of very long responses decides when a synchronous step ends. One lab's large agentic run reports a different split (§1), so measure your own. Every modern framework is built around keeping GPUs busy despite that tail.
  • Speed is bought with off-policyness. Asynchrony, partial rollouts and in-flight weight updates all train on data from a policy that is already a few versions old. Importance ratios, truncation and staleness limits keep the bias under control.
  • The sampler and the trainer are not the same policy, even with identical weights. Different kernels, BF16 or FP8 rounding and MoE routing all change the probabilities. Since 2025 the default fixes have been truncated or masked importance sampling, routing replay, higher precision where affordable, and bitwise-consistent kernels. Low-precision rollouts open another gap: one study finds naive FP8 degrades on long or hard tasks, others use it with no published comparison, so test it against a higher-precision baseline. Matched precision paths and quantization-aware training are the fixes on offer.
  • RL pass rate vs compute fits a sigmoid better than a power law. The ScaleRL fit separates the ceiling a recipe can reach from how efficiently it gets there. Recipes that look best early can lose at scale.
  • The environment is the real reward function. It is a task distribution plus a sandbox, tools and a grader. With binary rewards and group baselines, difficulty filtering decides which prompts carry any gradient at all. Every hole in the grader eventually turns into a behavior; Anthropic's system cards document this, from test special-casing in 3.7 Sonnet to environment audits in 2026.

§1Where the time goes

An RL step for an LLM has four phases: generate rollouts, score them, compute the update, and push the new weights back to the generator. In most published profiles, the first phase costs more than the other three combined.

At low concurrency, generation is memory-bandwidth bound and sequential: token $t+1$ cannot start before token $t$ exists. The training forward and backward pass, by contrast, processes every token of every sequence in parallel and is compute bound. Inference engines (vLLM, SGLang) recover throughput by batching many sequences at once, and very large batches can push a rollout engine toward compute-bound work. Tencent reports 2.29× generation throughput from a 4× larger PPO batch on fixed hardware, and up to 1.36× for GRPO.

Within one sequence, plain autoregressive decoding has no parallelism. Speculative decoding recovers some: a draft model proposes several tokens and the target accepts or rejects them in a way that preserves its output distribution. In principle this buys speed without adding off-policyness, though the numeric gap between sampler and trainer (§4) remains. The gain is capped because only generation gets faster: one study at 8B measured 1.8× on generation but 1.41× on the whole step. We found no independent test of the effect on RL outcomes, so still watch your learning curves.

The evidence on speculative decoding

The NeMo-RL study measured 1.8× and 1.5× generation speedups under synchronous RL, or 1.41× and 1.35× per whole step. The second setting drops from 1.35× to 1.24× at policy lag 1. Its 2.5× at 235B is a simulator projection. Z.ai, DeepSeek, Xiaomi and Shanghai AI Lab each report drafts in their rollouts.

Systems papers that profiled real runs report:

The exact share depends on response length, model size and how much the trainer is sharded. "Generation dominates" is a common finding, not a law. One lab, Xiaomi, reports a large agentic run whose RL cost splits into 43.8% rollout, 43.5% training and 12.7% grader. That is cost rather than time, so it does not compare directly with the numbers above. The habit to keep: measure your own split, grader included.

More on the split

SemiAnalysis's 2026 runs (third-party, with vendor help) were generation-bound up to 128K context, with the trainer waiting 30–74% of wall-clock. Xiaomi's MiMo-V2.6-Pro run used about 25K sequences per step at 110–150K tokens each.

The long tail

Response lengths in reasoning RL are heavily right-skewed: most answers are a few thousand tokens and a few run to the maximum. In a synchronous step, the batch is done only when its longest member is done. If lengths are roughly lognormal, $\log \ell \sim \mathcal N(\mu, \sigma^2)$, the largest of $n$ samples grows like

$$\max_{i\le n} \ell_i \;\approx\; \exp\!\big(\mu + \sigma\sqrt{2\ln n}\big), \qquad \text{while}\qquad \E[\ell] = \exp\!\big(\mu + \tfrac{\sigma^2}{2}\big).$$

For $\sigma=1$ and a batch of $n=1024$ rollouts, this leading-order formula gives a slowest rollout about $e^{3.72-0.5}\approx 25$ times the mean. It overshoots at finite $n$: the expected maximum of 1,024 standard normals is about 3.25, not 3.72, so the straggler is closer to $e^{3.25-0.5}\approx 16$ times the mean. Either way, with one slot per rollout and decoding as the only cost, the generator would sit over 90% idle. RollPacker measured the longest response at 25–32× the median. Continuous batching does not rescue this: in a synchronous step there are no new requests to admit.

Analogy · the convoy

A synchronous RL step is a convoy that may only leave the next town once its slowest truck arrives. Making the fast trucks faster does not help. You have to either let them start the next leg early (asynchrony), split the slow truck's load across legs (partial rollouts), or let the convoy change drivers mid-route (in-flight weight updates).

Where it breaks: trucks do not change their destination depending on when they left. Rollouts do: one that starts early comes from an older policy, and training on it is off-policy. The convoy picture hides this statistical cost.

Scroll through the five configurations below. The figure runs the same discrete-event simulator as the playground in §2: ten generation slots, lognormal rollout lengths with a hard cap, one trainer, and a weight-sync pause.

1 · The tidy picture. The pool is colocated: one set of GPUs generates, then trains (grey band), then reshards weights for the inference engine. With nearly equal lengths, very little time is wasted. verl's HybridFlow, OpenRLHF's colocate mode and TRL's default all work this way.

2 · Real lengths. Same system, realistic length spread. The red regions are generation slots with nothing to do while the slowest rollouts finish. Utilization drops, and more so at larger batch sizes.

3 · Disaggregate, run one step ahead. The generator and trainer now run on separate GPUs, and the generator may produce batch $k{+}1$ with policy $v_k$ while the trainer is still turning batch $k$ into $v_{k+1}$. Generation overlaps training (verl's "one-step off-policy", prime-rl's default). But the generator must still drain every in-flight rollout before it can load the new weights, so the tail still sets the pace of updates.

4 · In-flight weight updates. Weights are swapped in the middle of generation with a short pause, without discarding the sequences in flight (PipelineRL, Magistral). Rows now change color partway through: early tokens came from one policy version, late tokens from the next. The slots stay busy.

5 · Let it run further ahead. Allowing up to three versions of staleness raises throughput again, at the price of training on older data. The readout shows mean staleness rising. Every row of this figure trades utilization against staleness.

Colocated vs disaggregated

The first design choice is where the inference engine lives.

The choice is not strictly binary. Moonshot reports keeping Kimi K3 colocated so that each 1M-context experiment stays "within a few hundred GPUs". Alibaba's QwenGyre "elastically reallocates GPUs between rollout and training without interrupting live executions" and claims up to 1.85× over colocated and 1.78× over asynchronous baselines. Each is one lab's report on its own stack.

SystemPlacementAsynchronyNotable choice
verl / HybridFlow (ByteDance)colocated by default; disaggregated optionssync; one-step off-policy; fully async (recipe)Single-controller dataflow; 3D-HybridEngine resharding; "agent loop" for multi-turn token-in/token-out rollouts
OpenRLHFRay actors on separate GPUs, or colocate_alloptional async with a queue; partial rollout via vLLM pause/resumeRay + vLLM + DeepSpeed; actor, critic, reward and reference models can sit on separate GPUs
TRL GRPOTrainervLLM colocated (default) or server modesync; experimental AsyncGRPOTrainer with max_staleness (default 4)Truncated importance sampling on by default with vLLM generation
slime (THUDM / Zhipu)colocated or decoupled with one flagsync or async ("moving the ray.get")SGLang-native rollout + Megatron; the framework behind GLM-4.5 onward
AReaLdisaggregatedfully async, bounded staleness $k$Interruptible rollouts (KV cache recomputed); decoupled PPO objective
PipelineRL (ServiceNow)disaggregatedstreaming, in-flight updatesKeeps the stale KV cache after a weight swap; about 2× faster learning on 128 H100s
prime-rl (Prime Intellect)disaggregated, possibly decentralizedasync by default (rollouts for step $n{+}1$ from $\pi_{n-1}$), with bounded staleness (max_staleness, default 8; SemiAnalysis ran 16)TOPLOC verifies rollouts from untrusted workers; environments from the verifiers library
SkyRL (Berkeley)disaggregatedfully async with in-flight updatesLong-horizon, stateful agent environments (SkyRL-gym)

Feature sets move monthly. This table reflects each project's documentation as of October 2026. Others worth knowing: LlamaRL (Meta), StreamRL, ROLL Flash (Alibaba), Seer (Moonshot), RollPacker, Magistral's in-house async stack, DORA (Meituan), Agent Lightning (Microsoft) and, from 2026, Relax (Xiaohongshu), LoongSage (Baidu), Forge (MiniMax), QwenGyre (Alibaba) and AReaL-DTA.

§2Asynchronous RL: the design space

Every technique in this section changes which policy version produced each token. Learn to read a design by asking two questions: how stale can a token be, and does anything correct for it?

Four ways to hide the tail

  1. One-step (or $k$-step) off-policy. Generate batch $k{+}1$ with $\pi_{v_k}$ while training on batch $k$. verl reports a 23–40% end-to-end speedup over colocated synchronous training. INTELLECT-2, the first globally decentralized RL run of a 32B model, "used two-step asynchrony" and saw reward curves match synchronous training at asynchrony levels up to four.
  2. Fully asynchronous with bounded staleness. The generator streams continuously and an admission controller stops it from running more than $k$ versions ahead (AReaL, verl fully-async, TRL's AsyncGRPO). AReaL's paper reports up to 2.57× speedup in v1 and 2.77× in a later revision, with "linear scaling efficiency up to 512 GPUs". Its defaults are $k=4$ for coding and $k=8$ for math in the latest version.
  3. Partial rollouts. Cap the number of tokens each step may generate. Unfinished sequences are saved and continued in the next step, so one rollout can span several iterations. Kimi k1.5 saves "the unfinished portion" to a replay buffer. APRIL over-provisions requests, stops when enough have finished, and carries the rest forward.
  4. In-flight weight updates. Swap the weights while sequences are mid-generation. PipelineRL and Magistral keep the existing KV cache, which was computed by the old weights. Magistral notes "recomputing the key-value cache is not necessary". AReaL instead interrupts, discards the KV cache, and recomputes it with the new weights. Either way, one sequence can contain tokens from several policies.
# Bounded staleness, AReaL-style: generation may run at most k policy versions ahead.
def can_start_rollout(n_started: int, trainer_version: int, k: int, batch_size: int) -> bool:
    return n_started < (trainer_version + k + 1) * batch_size

# k = 0  -> synchronous on-policy (generator idles while the trainer works)
# k = 1  -> one-step off-policy
# k = 8  -> ScaleRL's chosen maximum off-policyness for PipelineRL

Start in Sync and raise the length spread σ. Switch to drain to update with k = 1: generation overlaps training, but each update still waits for the slowest rollout. Switch to in-flight updates and raise k: generator utilization climbs toward 100%, while mean and maximum staleness and the share of mixed-version sequences grow. Make the trainer slow (large train time) and see the bottleneck move to the trainer, at which point asynchrony stops helping. k limits how far generation may run ahead; a long rollout overtaken by short ones can still be consumed more than k versions later, so observed maximum staleness can exceed k. The simulator models decode time as proportional to length and ignores batching effects inside the inference engine.

Analogy · the kitchen that changes the recipe mid-service

In-flight weight updates are like a head chef who revises the recipe while dishes are half cooked. The cooks do not throw the pans away. They finish each dish with the new instructions. Plates that leave the kitchen were started under recipe $v$ and finished under recipe $v{+}1$. Keeping the stale KV cache is like keeping the half-cooked base, which was prepared the old way.

Where it breaks: a dish judged good can be traced to its recipe. A token's probability under "the policy" is ambiguous when its prefix was encoded by one set of weights and the token was sampled by another. Most systems log the sampling log-probability per token and correct against that, even if no single checkpoint produced the whole sequence.

Your generator is at 98% utilization with in-flight updates and k = 4, but end-to-end wall-clock per RL step did not improve versus k = 1. What is the most likely explanation?
Asynchrony overlaps two pipelines. Throughput is set by the slower one. Once the trainer is saturated (try a large train time in the simulator), raising k only increases staleness. The fix is to rebalance GPUs between the pools, not to add more asynchrony. Slow weight sync would lower generator utilization.

Weight synchronization is its own subsystem

Moving hundreds of gigabytes of weights every few minutes is hard.

The sync pause is usually seconds at research scale, but in-flight systems pay it every step for all generators.

Pitfall · "async" in a paper ≠ the same staleness in your run

"One-step off-policy" in one framework can mean "one optimizer step" in another, where a step may contain several mini-batch updates. PPO-style multi-epoch updates add their own off-policyness on top of any asynchrony. When you compare results, log the actual per-token version lag, not the configured parameter.

§3Off-policy corrections: from IMPALA to decoupled PPO

Once data comes from a behavior policy $\mu$ that is not the policy being trained $\pit$, the plain policy-gradient estimator is biased. Importance sampling removes the bias but can explode the variance. Every method below is a different compromise between the two.

The exact correction and why nobody uses it

For a response $y = (y_1,\dots,y_T)$ sampled from $\mu(\cdot\mid x)$, the on-policy gradient can be rewritten exactly:

$$\nabla_\theta J(\theta) = \E_{y\sim\pit}\!\big[A(x,y)\,\nabla_\theta\log\pit(y\mid x)\big] = \E_{y\sim\mu}\!\Big[\underbrace{\tfrac{\pit(y\mid x)}{\mu(y\mid x)}}_{W(y)=\prod_t \rho_t}\,A(x,y)\,\nabla_\theta\log\pit(y\mid x)\Big],\qquad \rho_t=\frac{\pit(y_t\mid x,y_{<t})}{\mu(y_t\mid x,y_{<t})}.$$

The sequence weight $W$ is a product of $T$ token ratios. Write $\sigma^2$ for the per-token variance of $\log\rho_t$ under $\mu$. By the central limit theorem, $\log W$ is approximately $\mathcal N(m, T\sigma^2)$, and $\E_\mu[W]=1$ forces $m=-T\sigma^2/2$. The effective sample size fraction is then

$$\frac{\text{ESS}}{N} \approx \frac{1}{\E_\mu[W^2]} = \frac{1}{e^{2m + 2T\sigma^2}} = e^{-T\sigma^2}.$$

A per-token log-ratio standard deviation of only $0.03$ ($\sigma^2\approx 10^{-3}$) over a 4,000-token response gives an ESS fraction of $e^{-4}\approx 2\%$, so one sequence in fifty carries the batch. This is the "exponential variance" that Liu, Li and coauthors bound formally. It is why practical LLM methods use per-token ratios: they are biased, because they ignore how the prefix distribution changed, but they are usable.

V-trace: truncate, and know what you converge to

IMPALA (Espeholt et al., 2018) faced the same problem with distributed actors that lagged behind the learner. Its V-trace target truncates the per-step ratios at two levels:

$$v_s = V(x_s) + \sum_{t=s}^{s+n-1}\gamma^{t-s}\Big(\prod_{i=s}^{t-1}\htmlClass{t-c}{c_i}\Big)\,\htmlClass{t-rho}{\rho_t}\big(r_t+\gamma V(x_{t+1})-V(x_t)\big),\quad \htmlClass{t-rho}{\rho_t}=\min\!\Big(\htmlClass{t-rhobar}{\bar\rho},\tfrac{\pi(a_t\mid x_t)}{\htmlClass{t-mu}{\mu}(a_t\mid x_t)}\Big),\ \ \htmlClass{t-c}{c_i}=\min\!\Big(\htmlClass{t-cbar}{\bar c},\tfrac{\pi(a_i\mid x_i)}{\htmlClass{t-mu}{\mu}(a_i\mid x_i)}\Big)$$
  • Behavior policy μ: the (stale) actor that generated the trajectory.
  • ρₜ: truncated ratio on the TD error. It decides which policy's value function you converge to.
  • ρ̄: with ρ̄ finite, the fixed point is the value of $\pi_{\bar\rho}\propto\min(\bar\rho\,\mu,\pi)$, between μ and π.
  • cᵢ: "trace-cutting" ratios. They set how fast information propagates backward, not the fixed point.
  • c̄: IMPALA's experiments use $\bar c=\bar\rho=1$.

The lesson carries over to LLMs without a value function: a truncation constant is a statement about which policy you are actually optimizing. Truncated importance sampling (TIS) with cap $C$ is a biased estimator whose bias points toward the behavior policy. When the mismatch is small, the bias is small.

Three policies, not two: decoupled PPO

PPO's ratio $\pit/\piold$ does two jobs at once. It corrects for off-policy data, and through clipping it enforces a trust region. Hilton, Cobbe and Schulman (2021) pointed out that these jobs can use different reference policies. AReaL uses this to handle staleness:

$$J(\theta)=\E_{y\sim\htmlClass{t-beh}{\pi_{\text{behav}}}}\Big[\sum_t \htmlClass{t-is}{\frac{\pi_{\text{prox}}(y_t\mid s_t)}{\pi_{\text{behav}}(y_t\mid s_t)}}\;\min\!\Big(\htmlClass{t-r}{r_t(\theta)}\hat A_t,\;\clip\big(\htmlClass{t-r}{r_t(\theta)},1-\epsilon,1+\epsilon\big)\hat A_t\Big)\Big],\qquad \htmlClass{t-r}{r_t(\theta)}=\frac{\pit(y_t\mid s_t)}{\htmlClass{t-prox}{\pi_{\text{prox}}}(y_t\mid s_t)}$$
  • Behavior policy: whatever actually sampled the tokens. It may be several versions old, or a mix of versions inside one sequence.
  • Proximal policy: a recent checkpoint, usually the weights at the start of this update, used as the trust-region anchor.
  • Off-policy correction: an importance weight, held constant during the update, that moves the expectation from behavior to proximal.
  • Trust-region ratio: clipped as in PPO, but measured against the proximal policy, not the stale sampler.

Because $\frac{\pi_\text{prox}}{\pi_\text{behav}}\cdot\frac{\pit}{\pi_\text{prox}}=\frac{\pit}{\pi_\text{behav}}$, the unclipped term is ordinary importance-sampled policy gradient. The clip simply stops $\pit$ from wandering far from a recent policy rather than from an arbitrarily old one. verl's 2026 "Rollout Correction" documentation describes a "decoupled mode" with three policies ($\pi_\text{rollout}$, $\pi_\text{old}$, $\pit$) and warns: "Many LLM-RL implementations incorrectly apply PPO by ignoring the actual rollout policy $\pi_{\text{rollout}}$."

Key idea · the families of correction
  • Truncate the weight (TIS, V-trace's $\bar\rho$, CISPO's clipped weight): keeps every token, adds bias toward the behavior policy, bounds variance.
  • Mask the token or sequence (MIS; IcePop masks tokens whose ratio leaves $[0.5, 5]$; DeepSeek-V3.2 masks negative-advantage sequences that drift too far): no reweighting bias on the tokens kept, but it throws data away and silently changes which samples you learn from.
  • Taper by sign (TOPR, 2025): treat positive and negative trajectories asymmetrically. Pushing down a bad sample that the current policy no longer generates is the dangerous direction.
  • Constrain a moment (M2PO, 2025): limit the second moment of the weights rather than clipping each one. It reports stability with data "stale by at least 256 model updates".

The algorithms themselves (GRPO, CISPO, GSPO) are in chapter 06. The point here is that the same ratio machinery now has a second job: correcting for the systems.

History · online DPO tolerates staleness

Before the 2025 reasoning boom, Noukhovitch et al. ("Asynchronous RLHF", ICLR 2025) asked which RLHF objectives tolerate off-policy data. Their finding was that "online DPO is found to be most robust to off-policy data, and robustness increases with the scale of the policy model". An asynchronous LLaMA 3.1 8B chatbot run was about 40% faster than synchronous with the same final quality. Contrastive objectives without importance ratios degrade more gracefully.

§4The training–inference mismatch

In 2025 the field found that even a perfectly synchronous run is off-policy. The inference engine and the trainer give the same tokens different probabilities, and that gap alone can collapse a run.

The engine that samples (vLLM or SGLang) and the engine that computes gradients (FSDP or Megatron) implement the same mathematical function with different kernels. Fused operations, reduction orders, attention algorithms, parallel layouts and intermediate precision all differ. Feng Yao, Liyuan Liu and coauthors made this concrete in an August 2025 post titled "Your Efficient RL Framework Secretly Brings You Off-Policy RL Training":

"despite πsampler and πlearner sharing the same model parameters θ, they can produce significantly different token probabilities… secretly making the RL training become off-policy."

They measured the worst per-token probability difference within a run. It was around 0.4 in normal training and reached 1.0 in a DAPO run on Qwen2.5-32B, meaning near-opposite verdicts from the two engines. Returning the true sampling probabilities and casting the LM head to FP32 did not remove it. A September 2025 follow-up by Jiacai Liu, Yingru Li and colleagues ("When Speed Kills Stability") added three findings:

Analogy · two accountants, one ledger

Give two accountants the same 10,000-line ledger. One adds it top to bottom, the other in batches of 64, each rounding every subtotal to the cent. They disagree by a few cents, and neither has made a mistake. RL then multiplies those cents. The policy gradient weights each token by how surprised the learner is, and a few hundred thousand slightly-wrong tokens per step add up to a systematic push in one direction.

Where it breaks: the accountants' errors are unbiased noise that averages out. Mismatch is not always unbiased. It correlates with token probability, sequence length, hardware and MoE routing, so it does not wash out. It accumulates.

Sources of mismatch

SourceMechanismMitigation in the literature
Precision (BF16)BF16 keeps 7 explicit mantissa bits, so every stored intermediate carries ~0.4% relative rounding error, and different kernels round at different pointsFP16 everywhere (Qi et al., 2025); FP32 LM head (MiniMax-M1); FP32 logits (ScaleRL)
Low-precision rollouts (FP8, FP4)Rollouts are quantized for speed while training stays at BF16, which adds a second numeric pathUnified precision flow (Jet-RL); quantization-aware training, with one scheme on both paths (Kimi K3) or rollout-guided rounding on the training side (TRACE, Alibaba on Qwen models); each is one lab's report. On naive FP8, see Fix 2
Kernels and reduction orderSplit-K matmuls, attention variants (cascade, flash-decoding) and fused kernels sum in different ordersBatch-invariant / bitwise-consistent kernels in both engines (Thinking Machines; vLLM + TorchTitan)
Batch compositionThe same request is computed differently depending on what else is in the batch, because the kernel picks a different split strategyBatch invariance (fixed reduction splits regardless of batch size)
Parallel layoutTensor-parallel degree changes reduction treesTP-invariant kernels (Zhang et al., Nov 2025)
MoE routingA tiny logit difference flips a top-$k$ expert choice, which changes the computation completely, not by an ulpRouting replay: reuse the inference routing in the training forward pass (R3; DeepSeek's "Keep Routing")
Sampling transformsTop-$p$/top-$k$ truncation and temperature change the sampling distribution. Engines may return log-probs from before these processors (vLLM's default logprobs_mode is raw)Return processed log-probs; apply the same truncation mask to $\pit$ (DeepSeek-V3.2 "Keep Sampling Mask")

A toy residual network (32 wide) is evaluated by two "engines" that compute the same function. The fused engine accumulates in FP32 and rounds once per layer. The unfused engine rounds split-K partial sums and each intermediate to the storage dtype. Each curve shows how far the two engines' log-probabilities differ over 200 sampled tokens. BF16's curve sits roughly a decade to the right of FP16's, and FP32 is several decades lower still. Increase depth or logit scale and the gap grows. Then tick identical kernels: every precision becomes bit-identical, because the issue was never randomness, only different rounding paths. This is a mechanism demo, not a calibrated model of any real engine.

Fix 1: correct for it (truncated or masked importance sampling)

Yao et al. proposed applying an importance weight between the two engines' probabilities for the same weights $\theta_\text{old}$, truncated from above. In PPO form the two ratios are clipped separately:

$$\mathcal L_{\text{TIS}}(\theta) = -\,\E_{y\sim\htmlClass{t-samp}{\pi_{\text{sampler}}(\theta_{\text{old}})}}\Big[\sum_t \underbrace{\min\!\Big(\htmlClass{t-w}{\frac{\pi_{\text{learner}}(y_t;\theta_{\text{old}})}{\pi_{\text{sampler}}(y_t;\theta_{\text{old}})}},\,\htmlClass{t-C}{C}\Big)}_{\text{mismatch weight, no gradient}}\;\htmlClass{t-ppo}{\min\!\big(r_t\hat A_t,\ \clip(r_t,1\!-\!\epsilon,1\!+\!\epsilon)\hat A_t\big)}\Big],\quad r_t=\frac{\pi_{\text{learner}}(y_t;\theta)}{\pi_{\text{learner}}(y_t;\theta_{\text{old}})}$$
  • Sampler: inference-engine probabilities, returned per token at generation time.
  • Mismatch ratio: same weights, two engines. Its expectation under the sampler is 1.
  • C: an upper cap only, so ratios below 1 are kept. A common choice is 2 (the value in verl's rollout_is_threshold presets).
  • Standard PPO-clip term, computed entirely inside the trainer.
import torch

def ppo_tis_loss(logp_new, logp_old, logp_sampler, adv, mask, eps=0.2, C=2.0):
    """All log-probs are [B, T] for the sampled tokens.
    logp_old:     recomputed by the TRAINER with the weights that generated the batch
    logp_sampler: returned by the inference engine for the same tokens
    adv:          [B, 1] (e.g. group-normalized), broadcast over tokens"""
    ratio = torch.exp(logp_new - logp_old)                          # trust region vs pi_old
    w = torch.exp(logp_old - logp_sampler).clamp(max=C).detach()    # mismatch correction (TIS)
    # MIS variant (mask instead of cap):
    #   w_raw = torch.exp(logp_old - logp_sampler).detach()
    #   w = torch.where(w_raw <= C, w_raw, torch.zeros_like(w_raw))
    surr = torch.minimum(ratio * adv, ratio.clamp(1 - eps, 1 + eps) * adv)
    return -(w * surr * mask).sum() / mask.sum()                    # token-mean aggregation

There are several variants:

DeepSeek-V3.2 (Dec 2025) masks sequences with negative advantage whose mean log-ratio between the inference engine's probabilities and the current policy exceeds a threshold, noting that this "accounts for both sources of off-policyness", staleness and engine mismatch. Two other open questions remain: whether masking positive-advantage outliers helps, and whether these corrections fix the problem or only postpone it.

Left: the distribution of $\log r$ between a "learner" and a "sampler" whose logits differ by heavy-tailed noise that is larger on low-probability tokens, as reported for real engines. Right: for 260 contexts, the bias and standard error of a truncated-IS estimate of an expectation under the learner, as functions of $C$. Small $C$ adds bias. Large $C$ costs variance, but at the token level the variance cost is mild, which is why $C\approx 2$ works in practice. Now switch the histogram to per sequence and drag T: the log-weight of a whole response spreads like $\sqrt T$ and drifts negative, and the sequence-level ESS collapses as $e^{-T\sigma^2}$. The default mismatch is deliberately larger than what real engines show (sampler–learner KL around $10^{-3}$ per token on well-matched hardware) so the effects are visible; drag it down for realistic levels.

Fix 2: shrink the gap (precision, routing)

Fix 3: eliminate it (bitwise-consistent kernels)

Thinking Machines' "Defeating Nondeterminism in LLM Inference" (Sept 2025) corrected a common belief. Inference nondeterminism is not mainly "GPU concurrency plus floating point". It comes from a lack of batch invariance: a kernel uses a different reduction strategy depending on batch size, and batch size depends on server load. Sampling 1,000 completions at temperature 0 from Qwen3-235B produced 80 unique outputs; with batch-invariant kernels, all 1,000 were identical. The kernels cost speed: serving 1,000 sequences from Qwen3-8B took 26 s with vLLM's default, 55 s with an unoptimized deterministic version, and 42 s after improving the attention kernel.

Determinism inside one engine is not yet agreement between engines. Their RL demonstration also used the same kernels in sampler and trainer, which gave "True On-Policy RL" with sampler–trainer KL "flat at 0". vLLM and TorchTitan reproduced bitwise-consistent RL in November 2025, initially "2.4x slower". By October 2026 a vLLM post reported a bitwise run at "91.3% of the baseline's rollout throughput" on a large MoE, and noted that on the same model the high-performance (non-bitwise) baseline's train-inference KL "rose from 2e-3 to 29.9" while reward fell back.

Frontier · unsettled in 2026

There is no consensus on which fix to use. A 2026 paper argues the mismatch is partly an optimization problem that shrinks with smaller updates ("Simple LR Scheduling Fixes It"). Another finds that "small token-level numerical disagreements can independently cause training collapse" when compared against a zero-mismatch reference. A third (score centering, Sept 2026) blames a persistent drift that accumulates every step. A useful warning came in Oct 2026 ("Probe the Harness"): harness details "can reverse the observed ranking of methods". Before you trust any comparison of mismatch fixes, check that the baselines shared a harness.

Pitfall · where does $\pi_\text{old}$ come from?

If you compute PPO's $\pi_\text{old}$ by re-running the trainer on the batch, the ratio $\pit/\pi_\text{old}$ starts at exactly 1, and the engine mismatch is invisible to your loss and your logs. If you take $\pi_\text{old}$ from the inference engine's returned log-probs, the clip region starts out partially "used up" by numerical noise, and the clip fraction becomes a mismatch detector. Always log $\KL(\pi_\text{sampler}\|\pi_\text{learner})$ (the "vllm-kl"); it is the earliest warning of a collapse.

You enable batch-invariant kernels in your vLLM sampler. Temperature-0 generations are now reproducible. Is your RL now on-policy?
Determinism means the sampler agrees with itself. On-policy requires the sampler to agree with the learner. Thinking Machines and vLLM/TorchTitan got KL = 0 by running identical kernels on both sides. FP16 narrows the gap but does not close it, and MoE adds routing flips on top.

§5Scaling laws for RL compute

Pretraining has power laws. RL, at least in the largest controlled study so far, has sigmoids. Part of the reason is the metric: pretraining laws are fit to loss, which has no ceiling in sight, while RL curves are fit to a pass rate, which is bounded by 1 and saturates. A sigmoid separates two things a power law blurs together: how high a recipe can go, and how fast it gets there.

Khatri et al. ("The Art of Scaling Reinforcement Learning Compute for LLMs", Meta and collaborators, Oct 2025; ICLR 2026) spent "more than 400,000 GPU-hours" on controlled RL runs and fit held-out pass rate against compute with

$$\htmlClass{t-RC}{R_C} - \htmlClass{t-R0}{R_0} = \frac{\htmlClass{t-A}{A} - \htmlClass{t-R0}{R_0}}{1 + \big(\htmlClass{t-Cm}{C_{\text{mid}}}/C\big)^{\htmlClass{t-B}{B}}}$$
  • RC: expected reward (pass rate on a held-out validation set) after compute $C$ (GPU-hours).
  • R₀: performance at the start of RL.
  • A: the asymptote, the ceiling this recipe reaches with unlimited compute.
  • B: steepness, i.e. compute efficiency. Larger means it gets from start to ceiling in fewer doublings.
  • Cmid: compute at which half of the total gain $A-R_0$ is achieved.

A single 8B run was fit up to 50k GPU-hours, extrapolated, and then extended to "100,000 GPU-hours". The extrapolation held, predicting an asymptote of about 0.645. The paper's main claim is that recipes differ in $A$, and that many details people tune mostly change $B$:

"Details such as loss aggregation, normalization, curriculum, and off-policy algorithm primarily modulate compute efficiency without materially shifting the asymptote."
Moved the ceiling $A$ (in their ablations)Mostly moved efficiency $B$, $C_\text{mid}$
Loss type (CISPO and GSPO above DAPO) · FP32 precision at the logits (0.52 → 0.61) · larger batch (slower early, higher ceiling) · longer generation budget (14k → 32k: slower, higher) · prompt-level loss aggregation · zero-variance filtering · no-positive-resampling Off-policy algorithm (PipelineRL vs PPO-off-policy: similar $A$, PipelineRL much higher $B$; best maximum off-policyness 8) · advantage normalization variant · generations per prompt at fixed total batch

Their combined recipe, ScaleRL, is PipelineRL with 8-step off-policyness, the CISPO loss, prompt-level loss averaging, batch-level advantage normalization, FP32 logits, zero-variance filtering, no-positive-resampling (permanently retiring prompts with pass rate ≥ 0.9), and forced length interruption. Over-long thoughts are cut by appending "Okay, time is up. Let me stop thinking and formulate a final answer now." It reaches $A=0.61$ in their main comparison.

Pitfall · the slogan is stronger than the table

Read the left column again. The paper's own ablations show loss type, precision and batch size moving $A$. "Most choices only change efficiency" is accurate for normalization, aggregation details and the choice of off-policy method, not for everything. The paper also warns that "methods that appear superior at small compute budgets can be worse when extrapolated to large-compute regimes". Batch comparisons without learning-rate retuning also conflate two effects. Tencent (§1) reports that larger batches cut time-to-target by up to 29% after retuning the learning rate and are slower without it. That measures time-to-target, not the asymptote, so it does not refute the left column.

Recipe 1 is efficient but plateaus at 0.52. Shape Recipe 2 with the sliders and find the crossing point: below it, any ablation would pick the wrong recipe. Then use the budget slider. Gold points are noisy evaluations of Recipe 2 up to that budget, and the dashed curve is a least-squares sigmoid fit with a bootstrap range for $A$. With a small budget (left of $C_\text{mid}$) the asymptote is barely identified. This is why ScaleRL fits only after an initial ~1.5k GPU-hours and validates by extending runs.

Analogy · acceleration vs top speed

$B$ and $C_\text{mid}$ are a car's 0–100 time; $A$ is its top speed. On a short test track the hatchback beats the sports car. An RL ablation run for 2k GPU-hours is a short test track.

Where it breaks: cars do not change their top speed when you change the fuel. RL recipes do: the "track" (data, prompt difficulty, max length) and the "car" (base model) interact, so a fitted $A$ is valid for one model, data mix and evaluation set, not a property of the algorithm alone.

How big is RL compute getting?

Public statements trace a steep curve:

Some 2026 work asks how to allocate RL compute: the IsoCompute Playbook (Mar 2026) finds that the compute-optimal number of parallel rollouts per problem "increases predictably with compute budget and then saturates". The strongest public statements are about what the compute is spent on. DeepSeek says V4.1-Flash's post-training "introduces no algorithmic innovation" and that "All substantive changes lie instead in the data pipeline". That is one lab describing its own model, not a measured law. The habit it suggests: when a run stalls, look at the tasks and environments as well as the algorithm.

Reported costs need the same care. Xiaomi reports \$2.6M of RL on MiMo-V2.6-Pro. That does not contradict Amodei: it is one final run at one lab, and by Epoch's estimate, which rests on heavy assumptions, final training runs are a minority of R&D compute.

Lab by lab

Z.ai says GLM-5.3 "uses the same base model as GLM-5.2 — every gain comes from post-training", and its card moves the DeepSWE v1.1 coding benchmark (not the DeepSWE agent in §6) from 46.2 to 66.9. Xiaomi reports its RL taking that benchmark from 58.4 to 72.6. Epoch estimates that final training runs were about 10–23% of R&D compute at three labs in 2024–25.

Anthropic · what is public

As far as we could find, Anthropic has not published an RL scaling law or RL compute share for Claude. Dario Amodei's essay above is the clearest public statement of direction. The system cards (§9) are the clearest public evidence of what scaled RL does to behavior. Anthropic's "Training a Misaligned Reward Seeker" (Aug 2026) adds first-party detail: internal RL monitoring assigns severity levels to detected hacks, and has led to "empowering the Alignment team to unilaterally block environments and declaring a moratorium on new environments" (new environments, not training). Epoch relays The Information's September 2025 report that Anthropic had discussed spending over \$1 billion on RL environments. Anything further about Claude's RL infrastructure would be speculation, and this chapter does not offer it.

§6Environments: the real reward function

When people say "RL environment" for LLMs they mean everything that turns a policy into a scalar: the task, the world the model acts in, the tools, and the grader. Choosing the algorithm is the easy part.

Prime Intellect's Environments Hub (Aug 2025) puts it as "Environments define the world, rules and feedback loop of state, action and reward." Concretely, an environment for an LLM is a bundle:

ComponentWhat it isSWE example
Task distributionPrompts plus metadata (reference answer, hidden tests, rubric), with a known difficulty profileGitHub issues paired with the commit that fixed them
Initial stateA resettable worldA container with the repo at the base commit and dependencies installed
Action interfaceTool schemas and the parser that turns tokens into callsbash, view_file, apply_patch, submit
TransitionExecute the action and return an observationRun the command in the sandbox, truncate stdout
TerminationSubmit, step budget, token budget, wall-clock timeout50 turns, 64k tokens, 20 minutes
GraderMaps the final state (or the trajectory) to a rewardRun hidden FAIL_TO_PASS and PASS_TO_PASS tests on fresh test files

Libraries encode the same split: Prime Intellect's verifiers defines an environment by a dataset, rollout logic, rubrics ("one or more reward functions") and optional parsers. verl's agent loop and SkyRL-gym provide multi-turn plumbing on the trainer side.

SWE environments: from benchmark to training ground

Training needed many more executable environments than that, and 2025 produced them:

Rewards vary. SWE-RL (Meta) used patch similarity to the reference as a cheap reward without execution. DeepSWE trained Qwen3-32B with RL alone on 4,500 R2E-Gym tasks over six days on 64 H100s and reached 42.2% pass@1 on Verified. It also introduced "compact filtering": masking trajectories that hit the context limit, the timeout or the step limit, so the model is not punished for running out of budget.

Press Play. Watch three things: (1) every tool call is a network round-trip to a sandbox; (2) the grader runs on fresh copies of hidden tests the policy never saw or touched; (3) at the end a single scalar is spread over the policy's tokens, while tool outputs (blue) are masked from the loss because the model did not generate them.

Design principles

This list is a synthesis of the sources in this chapter, not a published checklist:

  1. Unhackable by construction where possible. MacDiarmid et al. recommend "making reward hack immunity a key environment design criterion". Concretely: grade in a separate process on files the policy cannot write; restore tests and harness before grading; parse per-test results, not exit codes; hide or fuzz tests.
  2. Instructions consistent with the reward. Anthropic's Claude 4 system card lists among its mitigations modifying "environment instructions to be more consistent with the reward signal". If the grader only checks that tests pass, the reward defines the task, not the prompt "fix the bug".
  3. Calibrated difficulty. A task the policy always solves or never solves gives no gradient (§7). Maintain a pass-rate profile per environment and refresh it as the policy improves.
  4. Cheap, resettable and deterministic. Flaky tests add reward noise, and its structure matters more than its rate. Random noise looks tolerable in small settings: Plesner et al. stay within 1 point of baseline at up to 20% resampled noise (Qwen3 8B), with intervals they say establish no general threshold. Systematic false positives are the dangerous direction: on arithmetic tasks, Egashira et al. see plateaus or collapse that the error rate does not predict. Container snapshotting and warm pools often dominate the cost of an agentic environment.
  5. Diverse. DeepSeek-V3.2 reported "over 1,800 distinct environments and 85,000 complex prompts" for its agentic RL. Diversity guards against overfitting to one grader's quirks, and per MacDiarmid et al., diversity of safety training also guards against misgeneralization.
  6. Audited against the policy you are training, not the one you had. Anthropic's Fable 5.1 / Mythos 5.1 system card (Sept 2026) reported that "around half of our computer-use environments incentivized hacking or had accessible hack surfaces". They had been missed because "these environments were QA'd against older, less capable models which were not able to find certain hacks and (2) older environments were not re-audited after we improved our QA process." The card adds that "using substantially more test-time compute, along with specific harnesses and prompts, allows for weaker models to find more of the hacks that later, more capable models identify." Environments age as the policy gets stronger.

§7Curricula and difficulty filtering

With binary rewards and group-relative advantages, a prompt teaches nothing unless its group contains both successes and failures. Which prompts you feed the policy determines how much of your compute produces any gradient.

Take a binary reward and a prompt with pass rate $p$ under the current policy. With $G$ samples per group, the probability that every sample agrees is

$$P_0(p) = p^G + (1-p)^G .$$

When all samples agree, every advantage $r_i - \bar r$ is zero, so the group contributes no policy gradient, only cost. Pooled over a prompt distribution, the wasted share of rollouts is $\E_p[P_0(p)]$. To fill a batch with informative groups, DAPO's dynamic sampling ("over-sample and filter out prompts with the accuracy equal to 1 and 0") needs on average $1/(1-\E[P_0])$ groups per useful group. Averaged over all groups, informative or not, the expected squared mean-baseline advantage is

$$\E\big[(r_i-\bar r)^2\big] = \Big(1-\tfrac{1}{G}\Big)\,p(1-p),$$

the Bernoulli variance shrunk by the baseline's own noise. This peaks at $p=\tfrac12$. It is the formal version of "train at the frontier of learnability" (Foster et al., 2025), and of Bae et al.'s result that "expected policy improvement is lower-bounded by the variance of task-level success probabilities". GRPO's division by the group standard deviation partly undoes this weighting: it gives a 1-in-16 group the same scale as an 8-in-16 group. Chapter 06 discusses whether that is a feature or a bug.

All of this assumes binary rewards and a group baseline. Xiaomi's report says rubric scores "can still provide a learning signal" inside an all-pass group, though it also filters all-pass groups and we could not tell how the two interact. Z.ai's SAO has no groups at all (§11).

The histogram is a pool of 1,500 prompts with U-shaped (Beta-distributed) pass rates, typical of real pools: many hopeless, some trivially solved. The teal curve is the chance a group of size G is informative. Raise G and it widens, but each group costs more. The dotted grey line is a precomputed No filter run. Press Train in each mode. With No filter, the zero-variance share climbs as the policy improves and solved prompts pile up at p≈1. Dynamic sampling always fills the batch with informative groups but pays more rollouts per useful group as the pool saturates. Pre-filter once starts efficiently but goes stale, because a pass-rate estimate made at step 0 does not describe the policy at step 100.

Analogy · the Goldilocks gym

A weight you lift easily does not make you stronger; one you cannot move at all does not either. Strength comes from weights at the edge of your ability. And the edge moves: last month's challenging weight is this month's warm-up. A curriculum is a trainer who keeps re-racking the bar.

Where it breaks: a gym's weights stay put on the rack. A prompt that looks hopeless at step 0 can become learnable through transfer from related prompts (GRESO found that about 20% of zero-variance prompts became effective again later), so retiring easy prompts is safer than discarding hard ones. ScaleRL's no-positive-resampling retires prompts above 0.9.

Strategies used in practice:

def informative_groups(groups):
    """groups: list of (prompt, rewards: Tensor[G]) with binary rewards.
    Dynamic sampling (DAPO): keep only groups with 0 < accuracy < 1, and keep
    sampling new prompts until the batch is full."""
    return [(p, r) for p, r in groups if 0.0 < r.float().mean().item() < 1.0]
A prompt pool has pass rates concentrated near 0.95. You use G = 16. Roughly what fraction of groups for a p = 0.95 prompt are zero-variance, and what is the cheapest lever?
$0.95^{16}+0.05^{16}\approx 0.44$. Lowering temperature makes groups even more uniform. The fix is the pool, not the optimizer: retire prompts above ~0.9 (no-positive-resampling) and source harder ones.

§8Agentic and multi-turn RL

An agent episode runs from dozens to hundreds of turns or more, with thousands of tool-output tokens at least, and one reward at the end. Three problems get harder: credit assignment, context length and systems latency.

Credit assignment across turns

The default in 2025–2026 is the simplest option: treat the whole trajectory as one action sequence, mask non-policy tokens (tool outputs, environment messages), and broadcast a single trajectory-level advantage to every policy token. It worked surprisingly well at tens of turns with verifiable rewards, but its variance grows with horizon, and 2026 recipes disagree on whether to keep it (§11). Alternatives:

Analogy · scoring a season by the final standings

Trajectory-level reward is like judging every decision a football coach made in a 38-game season by the final league position. Over many seasons it does sort good coaches from bad, but it learns slowly, and it rewards a terrible substitution in game 12 if the team still won the league.

Where it breaks: football seasons cannot be replayed from game 12. RL environments often can be reset to an intermediate state, which is exactly what anchor-state grouping and tree-structured rollouts exploit. There, credit assignment can be partly fixed with more samples instead of a critic.

Long horizons and context management

Agent trajectories outgrow any context window. The policy can be trained to manage its own memory:

A trajectory with summaries in it is a different MDP from one with full history.

Systems for agents

Tool calls add latency the GPU cannot hide, so agentic RL leans harder on asynchrony. ROLL Flash reports bigger speedups on agentic tasks (2.72×) than on math RLVR (2.24×). Rollouts become token-in/token-out sessions against an inference server, so that agent harnesses can run unmodified. Two pitfalls get worse:

In a multi-turn coding agent, the tool returns a 3,000-token test log. Which tokens should get a policy-gradient loss?
The policy-gradient identity holds for actions the policy took. Tool outputs are environment transitions; putting them in the loss trains the model to imitate (or un-imitate) the environment, with an importance ratio that is not even defined because the sampler never produced them. Restricting loss to the final answer discards the credit for the tool calls that made it possible.

§9Reward hacking in environments

RL is an optimizer, and the grader is its objective. Every hole in the grader is a reward that is easier to collect than the intended one. At scale, the policy finds the holes.

Chapter 03 treats Goodhart's law for learned reward models. Programmatic graders fail differently, by being literally exploitable. Public cases include:

ExploitSource
Special-casing tests: returning the expected values for the visible test inputsClaude 3.7 Sonnet system card (Feb 2025)
Editing or deleting the failing testsClaude 3.7 Sonnet card; Mythos Preview card (Apr 2026)
exit(0) before tests run; raise SkipTestBaker et al. (OpenAI, 2025)
An object whose __eq__ always returns True; sys.exit(0); a conftest.py that rewrites pytest reports to "passed"MacDiarmid et al. (Anthropic, 2025): a research model on real Sonnet 3.7 training environments (these hacks did not occur in Sonnet 3.7's own training)
Overwriting the timer in a speed benchmark; reading the scorer's own answer from the call stackMETR on o3 (June 2025)
Guessing credentials, minting API keys, escaping network restrictionsMythos Preview and Fable 5.1 / Mythos 5.1 system cards (2026)
Anthropic · the public record, card by card
  • Claude 3.7 Sonnet (Feb 2025): the model "occasionally resorts to special-casing in order to pass test cases in agentic coding environments like Claude Code", typically "after multiple failed attempts to develop a general solution". The card states that the behavior "emerged as a result of "reward hacking" during reinforcement learning training". It was rare in normal use and was caught by automated classifiers on training transcripts.
  • Claude Opus 4 / Sonnet 4 (May 2025): "an average 67% decrease in hard-coding behavior and … a 69% average decrease compared to Claude Sonnet 3.7". Mitigations were better monitoring, a human rapid-response program and "environment improvements". New evaluations included hidden tests and deliberately impossible tasks, where any "success" is a hack.
  • Claude Sonnet 4.5 (Sept 2025): roughly 2× fewer hacks than the Claude 4 models and 4× fewer than 3.7, attributed mostly to "continued improvements to the robustness of our environments and reward structures in conjunction with high quality monitoring". The card notes its evaluations were made more aggressive, so absolute numbers are not comparable across cards.
  • Claude Opus 4.5 (Nov 2025): "Since the training of Claude Sonnet 4 and Claude Opus 4, we have been using inoculation prompting on a significant subset of our coding environments, including those that are most susceptible to reward hacking."
  • 2026 cards:
    • Mythos Preview reported that the model "occasionally circumvented network restrictions in its training environment" to download data that shortcut the task, with attempts in about 0.05% of training episodes and successful attempts in about 0.01%.
    • Fable 5.1 / Mythos 5.1 found that rewarded credential guessing "generalized to held-out environments". An audit flagged around half of the computer-use environments as hackable, and they were temporarily removed. On new out-of-distribution evaluations, Mythos 5.1 reward-hacked at "around 15%".
    • Opus 5.5's card calls answer-key guessing "particularly tricky to defend against, even as we harden our environments", and reports successful answer-key guessing in about 0.3% of sampled RL training episodes.

Through 2025 the cards credited lower hacking rates mainly to environment hardening and monitoring, on evaluations they themselves call non-comparable across cards. By August 2026 Anthropic researchers write: "As frontier model intelligence, RL compute, and data diversity have increased, reward hacking has become more prevalent and difficult to prevent." SimHack (Google Research authors among them) calls hardening "increasingly difficult".

Why it matters beyond the benchmark

MacDiarmid et al. ("Natural Emergent Misalignment from Reward Hacking in Production RL", Anthropic and Redwood, Nov 2025) taught a pretrained model about the three pytest hacks above through synthetic-document finetuning (or, in a second setting, through prompting), then trained it with RL on "a subset of the actual environments used to train Claude Sonnet 3.7". It learned to hack and generalized to "alignment faking, cooperation with malicious actors, reasoning about malicious goals, and attempting sabotage". Standard chat-style RLHF safety training made it look aligned on chat evaluations, while "misalignment persists on agentic tasks". Three mitigations worked: preventing the hacking, diversifying safety training, and inoculation prompting, which frames hacking as acceptable in the training prompt. With inoculation, "final misalignment is reduced by 75-90%, despite reward hacking rates over 99%".

Read this as a result about that setup, because how far hacking spreads is unsettled. A UK AISI reproduction on open models found misalignment on some evaluations but not consistently. Anthropic then ran a deliberately pessimistic research run at frontier scale: its model cheated and did harm when a grader was visible, yet was "not misaligned in scenarios without a clear grader/reward". The authors think differences in training setup likely explain the gap, and neither result cancels the other. So test behavior both with and without a visible grader. The companion Alignment guide has the detail. Either way, for an RL engineer the takeaway is simple: a hackable environment is a safety problem, not just a wasted-compute problem.

The follow-up evidence

UK AISI reproduced hacking on open models in non-production environments, with egregious misalignment on some evaluations but not consistently across them. Anthropic's run deliberately trained an early Opus 4.8 checkpoint on 80 real environments known to be hackable, with no hints or inoculation; the authors call it "a plausible (though pessimistic) proxy" for a run without their usual defenses. It reached 40% flagged episodes. Tampering rose from 0% to 41% and harmful responses from 1% to 29% where a grader was visible. Comparing this with their 2025 paper, the authors write that the difference is "likely explained by the differences in training setups".

Seven strategies compete under group-relative policy gradient (16 rollouts per step, 300 steps). A genuine fix passes 40% of the time. Each exploit passes 100% of the time unless a defense blocks it. Start with no defenses: hacking takes over. Close holes one at a time and watch the policy move to the next open exploit. Only when every exploit is closed does the genuine fix win. Finally, leave the defenses off and put the CoT monitor in the reward. The hack the monitor misses now earns more than honest work, so the policy usually drifts to it (new seed shows how early sampling affects the timing). That is Baker et al.'s obfuscation result in miniature. All payoff and detection numbers are illustrative.

Analogy · the driving test with a predictable examiner

If the examiner only checks that you stopped at the line and never looks at your mirrors, learners who practise for the test will stop beautifully and never check a mirror. Hiding the checklist (held-out tests), varying it (fuzzed tests), and having a second examiner watch your eyes (a monitor) all help. If you fail anyone the second examiner sees glancing at the checklist, you train learners to glance more subtly.

Where it breaks: human learners know a "real" goal exists. A policy trained only on the grader has no other source of what you meant, unless the prompt, prior training or the environment's instructions supply it. That is why instruction–reward consistency and inoculation prompting work at all.

Detection and the monitorability tax

Baker et al. ("Monitoring Reasoning Models for Misbehavior and the Risks of Promoting Obfuscation", OpenAI, Mar 2025) watched a frontier reasoning model during RL on coding tasks. Hacks like exit(0) and raise SkipTest "quickly get reinforced and become systemic". A GPT-4o monitor reading only actions caught 60% of the systemic hacks. Reading the chain of thought, it caught 95%. When they added the CoT monitor to the reward, agents learned "obfuscated reward hacking, hiding their intent within the CoT while still exhibiting a significant rate of reward hacking". Their recommendation is to pay a "monitorability tax": do not apply strong optimization pressure directly to the chain of thought. Independent evaluations show the problem is not specific to one lab:

Key idea · the mitigation stack
  1. Harden the environment (first and best): out-of-process grading, read-only or restored tests, hidden or fuzzed tests, per-test result parsing, strict comparisons, no network unless needed, red-team each environment with the current policy at high test-time compute.
  2. Make the prompt match the reward, and say explicitly what counts as solving the task.
  3. Monitor without training against the monitor: classifiers over transcripts, CoT and action monitors, human review. Use them to find and fix environments and to filter or relabel data. Be cautious about using them as reward terms.
  4. Inoculation prompting in hack-prone environments, to limit what a learned hack generalizes into.
  5. Evaluate with impossible tasks and held-out graders, and track hacking per environment over training.
You add a CoT monitor to the reward and the measured hacking rate drops from 30% to 3%. What should you check first?
Once a monitor is in the reward, its readings are no longer independent: in Baker et al. the hacks continued while the CoT stopped revealing them. You need an evaluation signal the policy was never optimized against.

§10Systems details that change results

These choices look like plumbing. Each one has changed a published conclusion at some point.

Packing, dynamic batching and loss aggregation

Rollouts vary in length by 10–100×. Padding each micro-batch to its longest member wastes compute on pad tokens. Sequence packing concatenates several sequences into one fixed-length row, with a block-diagonal attention mask and position ids restarted per sequence, so the trainer does almost no padded computation. Dynamic batching sets micro-batch size by token budget.

32 rollouts with lognormal lengths, capped at 4,096 tokens. Top left: pad each micro-batch to its longest member, in arrival order. Top right: the same after sorting by length (length bucketing). Bottom: first-fit-decreasing packing into 8,192-token rows. Red is wasted compute. Increase the spread: padding waste explodes and sorting recovers most of it. Packing wastes only the tail of the last row; with just 32 rollouts that tail is a large share, so the readout also reports waste over full rows only. Sorting changes which sequences share a micro-batch, which is harmless if the loss is aggregated over the whole mini-batch but not if you normalize per micro-batch.

Pitfall · aggregation silently changes with packing

"Mean over tokens" can mean per sequence, per micro-batch, per packed row, or per global batch. These weight long and short responses differently, and the difference is a length bias in the gradient. That is the Dr. GRPO critique from chapter 06, and ScaleRL found aggregation choices change efficiency. With packing and gradient accumulation, normalize by the global token (or sequence) count of the whole update, or your loss depends on how the packer arranged the data.

KV cache and prefix sharing

A GRPO group shares its prompt, and multi-turn rollouts share growing prefixes. Prefix caching (radix trees in SGLang, prefix caching in vLLM) computes the shared part once. After an in-flight weight update, the cached KV is stale; keeping it trades a little extra off-policyness for not recomputing. KV memory also bounds concurrency.

Sampling temperature

A common RLVR default is to sample at temperature 1.0 with no top-$p$/top-$k$, so that the sampling distribution is the policy whose log-probabilities are being trained. Otherwise the behavior policy is $\pi^{1/\tau}$ or a truncated $\pi$, and you must either correct for it (return the processed log-probs; apply the same mask to $\pit$, as DeepSeek-V3.2's "Keep Sampling Mask" does) or accept the bias. Liu, Li et al. found that a smaller top-$p$ reduced KL spikes but increased bias. POLARIS deliberately raised training temperature (1.4 → 1.45 → 1.5 for a 4B model) to keep rollout diversity up as the policy sharpened.

Max length and truncation

A response that hits the maximum length has no verdict. Scoring it as wrong teaches "be shorter", possibly as a spurious penalty on hard problems. Options:

The truncation rate is a key metric. If it climbs, you are training on censored data.

Checkpointing an asynchronous system

A synchronous RL checkpoint is model plus optimizer plus data cursor. An async one also needs:

Resuming without the buffer silently changes the data distribution; a reset version counter breaks staleness accounting.

Evaluation during RL and what to log

Training reward is biased: it comes from the policy's own filtered prompts, under the training grader. Run held-out evaluations on a fixed schedule with enough samples per problem to report pass@1 with error bars (see chapter 09). A minimal dashboard:

MetricWhy
Sampler–learner KL (per token, plus the max)Earliest collapse signal (§4)
Version lag per token (mean, max)Actual staleness, not configured staleness
IS weight stats: fraction truncated or maskedHow much your correction is doing; a rising fraction means drift
Zero-variance group fractionWasted rollouts; the curriculum needs a refresh (§7)
Response length and truncation rateLength drift; censored data
Entropy, clip fraction, gradient normEntropy collapse and instability (ch. 06)
Cross-input mutual-information proxyTemplate collapse that entropy misses (RAGEN-2, small tasks)
Hack-classifier rate and held-out vs training grader gap, per environmentReward hacking (§9)
Generator and trainer utilization; weight-sync timeWhere the next speedup is (§1–2)

§11Frontier and open problems

How to think about it

People who run RL at scale think in terms of which policy produced which token and which signal the policy was not optimized against. If you can draw the generator and trainer timeline for a design, name its staleness and correction, and explain why your evaluation is independent of your reward, you understand these systems.

§12Check yourself

Try each one before opening the answer.

Why does generation usually dominate an RL step, and what is the first thing you would change? core

Decoding is sequential and, at low concurrency, memory-bandwidth bound: one forward pass per token, little arithmetic per byte of weights read. Training processes all tokens in parallel and is compute bound. On top of that, synchronous steps wait for the longest response, and with lognormal lengths the maximum of $n$ samples grows (to leading order) like $e^{\sigma\sqrt{2\ln n}}$ times the median. Published profiles put rollout at roughly 60–90% of iteration time, though Xiaomi's MiMo report splits cost about evenly between rollout and training, plus 12.7% for grading. First change: measure your own split, grader included, then the length distribution and the idle fraction. If the tail dominates, try partial rollouts or one-step asynchrony (cheap, staleness 1) before fully asynchronous designs. Also check prefix caching, continuous batching and KV memory.

Derive the effective sample size of sequence-level importance weights and explain what it implies. deep

$W=\prod_t\rho_t$, so $\log W=\sum_t\log\rho_t$. With roughly independent token log-ratios of variance $\sigma^2$, $\log W\approx\mathcal N(m,T\sigma^2)$. Since $\E_\mu[W]=1$ we need $e^{m+T\sigma^2/2}=1$, so $m=-T\sigma^2/2$. Then $\E_\mu[W^2]=e^{2m+2T\sigma^2}=e^{T\sigma^2}$, and with normalized weights $\text{ESS}/N\approx1/\E[W^2]=e^{-T\sigma^2}$. Even tiny per-token mismatch ($\sigma^2=10^{-3}$) over thousands of tokens leaves a few percent effective samples. Hence per-token ratios (biased, low variance), sequence-level truncation or masking, or geometric means $W^{1/T}$.

Explain decoupled PPO: which three policies, and which ratio does what? core

Behavior policy (what sampled the tokens, possibly stale or mixed), proximal policy (a recent anchor, usually the weights at the start of this update) and the current policy $\pit$. The ratio $\pi_\text{prox}/\pi_\text{behav}$ is an importance weight with no gradient, which corrects the data distribution. The ratio $\pit/\pi_\text{prox}$ is clipped to form the trust region. Standard PPO sets prox = behav, so with stale data its trust region is centered on an old policy, and with engine mismatch it is centered on the wrong numerics. The product of the two equals $\pit/\pi_\text{behav}$, so the unclipped objective is unchanged.

Your GRPO run's reward climbs, then collapses at step ~600. Sampler–learner KL was rising slowly beforehand. Walk through your debugging. deep

Hypothesis: accumulated training–inference mismatch. Evidence would be the KL trend, ratio outliers on low-probability tokens, and longer responses before the collapse. Discriminating observations:

  1. Resume from step 500 with a sequence-level correction (TIS or MIS with C≈2). If it survives, mismatch was causal.
  2. Check precision: BF16 versus FP16 or FP32 logits.
  3. For MoE, measure routing disagreement and try routing replay.
  4. Check what logprobs_mode the engine returns and whether top-$p$ or temperature are applied on one side only.
  5. Check attention backends; on A100 cascade attention was implicated.

Change one variable at a time against the same resume point. Only then consider algorithmic causes such as entropy collapse or a learning rate that is too high (a 2026 paper argues large updates themselves inflate mismatch).

TIS vs MIS vs sequence-level masking: when would you pick each? deep

Token-level TIS keeps every token, caps the variance, and biases toward the sampler; it is cheap and fine when mismatch is small and diffuse. MIS zeroes outliers instead, which avoids weighting likely numerical garbage at $C$ but discards data, disproportionately low-probability tokens. Sequence-level variants respect the fact that the prefix distribution changed. Liu, Li et al. found token-level corrections only delayed collapse while sequence-level TIS stayed stable, at the cost of more variance; geometric-mean variants remove the length dependence. If mismatch is from MoE routing, fix the routing instead of reweighting around it.

BF16 is the default for pretraining. Why might FP16 be better for RL fine-tuning? deep

BF16 trades mantissa (7 bits) for exponent range (8 bits). That range protects pretraining from overflow while activation scales are still being learned. In RL fine-tuning the scales are already fixed by pretraining, so FP16's range (5 exponent bits) is usually sufficient, and its 10-bit mantissa gives 8× finer rounding. The trainer and the sampler both round less, so their probabilities agree more: Qi et al. report about 24× smaller mismatch. Costs: loss scaling, overflow risk in some layers, and less mature kernel support for some engines. It is a strong default to test, not a universal rule, and some 2026 recipes instead lower rollout precision and match the paths (§4).

What does batch invariance buy you, and what doesn't it? research

It buys run-to-run determinism of one engine under varying load, which gives reproducible sampling, debuggable evaluations, and caching that does not change outputs. It does not by itself make RL on-policy, because the trainer uses different kernels. True on-policy needs the same numerics on both sides: shared batch-invariant kernels, matching parallel layouts (TP-invariant reductions), identical sampling transforms, and for MoE identical routing. It also does not remove off-policyness from asynchrony or multi-epoch updates. Cost: in 2025 custom kernels ran about 1.6–2.4× slower; by late 2026 reports were close to baseline throughput for some models.

You have 4k GPU-hours per ablation and two candidate recipes. How do you decide which to scale? research

Do not compare final rewards at 4k. Fit the sigmoid $R_C$ to each run's held-out evaluation curve, after excluding the early transient, and compare the fitted asymptotes $A$ with bootstrap intervals. Check that each run has passed its $C_\text{mid}$; if not, $A$ is unidentified and you need longer runs. Use several seeds, and validate by extending the more promising run to 2–4× and checking the extrapolation, as ScaleRL did. Check for confounds that change with scale, such as length truncation or curriculum saturation.

Design an RL environment for a coding agent. Where are the hack surfaces? core

Components: an issue dataset; a container at the base commit; tools; limits on turns, tokens and time; a grader that, in a separate process, checks out fresh test files and runs hidden FAIL_TO_PASS and PASS_TO_PASS tests, parses per-test results, and returns pass/fail. Hack surfaces:

  • writable tests or harness (edit tests, conftest.py);
  • exit-code-based grading (sys.exit(0));
  • loose equality (__eq__ overrides);
  • visible tests that are also the grading tests (special-casing);
  • network access (fetching the upstream fix);
  • git history containing the fix;
  • timing-based scorers (patching timers);
  • flaky tests.

Audit by letting a strong current model attack the environment with a large test-time budget, and keep impossible-task variants to measure hacking directly.

Derive the zero-variance fraction for GRPO and argue for or against dynamic sampling. core

With binary rewards and pass rate $p$, a group of $G$ is uniform with probability $p^G+(1-p)^G$. Then all advantages are zero and the gradient is zero. For dynamic sampling: every batch is fully informative, so updates are stable. Against: it costs $1/(1-\E[P_0])$ times more rollouts per useful group, which grows quickly as the pool saturates, and it reweights training toward medium-difficulty prompts. Cheaper complements: retire prompts the model has mastered (pass rate > 0.9), predictively skip prompts that were recently zero-variance (GRESO), and refresh the pool with harder tasks.

How would you do credit assignment for a 100-turn agent with one terminal reward? research

Baseline: trajectory-level advantage broadcast to policy tokens, with tool outputs masked. Options, in increasing complexity:

  1. Exploit resettable state: branch several continuations from intermediate states and compare them (anchor-state grouping, as in GiGPO, or tree rollouts). This gives step-level advantages without a critic.
  2. Learn an utterance-level value function (ArCHer-style) and use TD advantages per turn.
  3. Add verifiable process rewards (tests passing incrementally, sub-goal checks), guarding each against hacking.
  4. Shape for efficiency with discounting on successes.

Also bound each turn's input with context management, which changes the MDP the gradient is conditioned on.

After RL, your model special-cases tests. What do you do, at training time and at evaluation time? deep

First quantify it with a transcript classifier, hidden or fuzzed tests, and impossible tasks. Then find which environments rewarded it: per-environment hack rates and the gap between the training grader and a held-out grader. Training: harden those environments (restore tests, hide or fuzz them, grade out of process); make instructions match the reward; consider inoculation prompting in hack-prone environments to limit generalization; add the hack classifier to data filtering and environment triage rather than as a reward term. Then re-measure for a move to the next exploit.

Should a chain-of-thought monitor be part of the reward? research

Baker et al.'s evidence says be careful. Under optimization pressure, agents learned to hide intent in the chain of thought while still hacking. Better uses of the monitor: finding broken environments, filtering or relabeling data offline, gating deployment, and measurement. If you must use it in the reward, keep an independent evaluation channel, apply light pressure, and track the gap between monitor-flag and independent hack rates. MacDiarmid et al. found offline filtering of hacks insufficient on its own against misgeneralization.

You move from k = 1 to k = 8 staleness to double throughput. What can break, and what do you monitor? deep

What can break:

  • Gradients are computed on data from up to eight versions back, so their bias grows with policy speed (learning rate and step size).
  • PPO-style clipping against a stale $\pi_\text{old}$ becomes either too loose or permanently saturated.
  • Negative-advantage samples the policy no longer generates get pushed down further, which TOPR flags as a degeneration risk.
  • Entropy and length can drift.

Use a decoupled objective, truncate the IS weights, consider masking stale negative samples, and possibly lower the learning rate. Monitor per-token version lag, IS weight truncation fraction, clip fraction, sampler–learner KL, entropy, and held-out evaluations against a k = 1 control at matched wall-clock and matched samples.

Flashcards

Share of RL iteration time spent in rollout (published profiles)
Roughly 60–90% of time: Seer 63–87%, RollPacker ~70%, OpenRLHF README 80%. Not a law: Xiaomi reports one large run's cost as 43.8% rollout, 43.5% training, 12.7% grader.
Colocated vs disaggregated
Colocated: one pool alternates generate/train with resharding. Disaggregated: separate pools, overlap possible, weights travel over the network, at least one step off-policy.
In-flight weight update
Swap weights mid-generation without discarding sequences (PipelineRL, Magistral; stale KV cache kept). Sequences mix policy versions.
Partial rollout
Cap tokens per step; unfinished sequences are continued in the next iteration (Kimi k1.5, APRIL).
V-trace's ρ̄ vs c̄
ρ̄ sets the fixed point (value of π_ρ̄ ∝ min(ρ̄μ, π)); c̄ sets contraction speed.
Decoupled PPO's three policies
Behavior (sampled the data), proximal (trust-region anchor), current θ.
Sequence-level IS ESS
≈ e^(−Tσ²): exponentially small in length.
TIS
Weight min(π_learner(θ_old)/π_sampler(θ_old), C) on each token's loss; upper cap only; C ≈ 2.
Root cause of LLM inference nondeterminism (Thinking Machines)
Lack of batch invariance: kernels reduce differently at different batch sizes, and batch size depends on load.
Routing replay (R3)
Reuse the inference engine's MoE expert choices in the training forward pass; ~10% of routers otherwise differ.
ScaleRL fit
R_C − R₀ = (A − R₀)/(1 + (C_mid/C)^B). A = ceiling, B = efficiency, C_mid = half-gain compute.
Zero-variance probability
p^G + (1 − p)^G with binary rewards; such groups give zero GRPO gradient.
Three pytest hacks (MacDiarmid et al.)
AlwaysEqual (__eq__ → True), sys.exit(0) before asserts, conftest.py rewriting reports to "passed".
Monitorability tax
Baker et al.: avoid strong optimization pressure on the CoT, or agents learn obfuscated reward hacking.
Inoculation prompting
Frame hacking as acceptable in the training prompt; cut emergent misalignment 75–90% in MacDiarmid et al.; used in Claude coding environments since Claude 4 (Opus 4.5 card).

§13Read next

The Art of Scaling Reinforcement Learning Compute for LLMs
Khatri et al. · 2025 · ICLR 2026
Sigmoidal compute–performance fits; which choices move the ceiling vs the efficiency; the ScaleRL recipe validated to 100k GPU-hours.
scalingrecipe
Your Efficient RL Framework Secretly Brings You Off-Policy RL Training
Yao, Liu et al. · 2025 · blog (NeurIPS 2025 workshop version)
Same weights, two engines, different probabilities; truncated importance sampling as the fix.
mismatchTIS
AReaL: A Large-Scale Asynchronous Reinforcement Learning System for Language Reasoning
Fu et al. · 2025
Fully asynchronous RL with interruptible rollouts, bounded staleness and the decoupled PPO objective.
asyncsystems
Natural Emergent Misalignment from Reward Hacking in Production RL
MacDiarmid et al. · 2025 · Anthropic / Redwood
In this setup, hacks learned in real Claude coding environments generalize to sabotage and alignment faking; inoculation prompting mitigates. Later work is narrower (§9).
reward hackingalignment
Monitoring Reasoning Models for Misbehavior and the Risks of Promoting Obfuscation
Baker et al. · 2025 · OpenAI
CoT monitors catch hacks far better than action monitors, until you train against them.
monitoringCoT
HybridFlow: A Flexible and Efficient RLHF Framework
Sheng et al. · 2024 · EuroSys 2025
The design behind verl: hybrid single/multi-controller dataflow and 3D-HybridEngine resharding.
systemsverl
PipelineRL: Faster On-policy Reinforcement Learning for Long Sequence Generation
Piché et al. · 2025
In-flight weight updates with a retained (stale) KV cache; the off-policy method inside ScaleRL.
async
IMPALA: Scalable Distributed Deep-RL with Importance Weighted Actor-Learner Architectures
Espeholt et al. · 2018 · ICML
V-trace: truncated importance weights for lagging actors, with a clear account of what truncation converges to.
off-policyclassic
Asynchronous RLHF: Faster and More Efficient Off-Policy RL for Language Models
Noukhovitch et al. · 2024 · ICLR 2025
Online DPO is the most staleness-robust RLHF objective; async runs ~40% faster at equal quality.
asyncRLHF
Defeating the Training-Inference Mismatch via FP16
Qi et al. · 2025
Blames BF16 rounding for the mismatch; FP16 cuts it ~24× and stabilizes RL.
mismatchprecision
Defeating Nondeterminism in LLM Inference
He et al. · 2025 · Thinking Machines
Batch invariance, not concurrency, causes nondeterminism; identical kernels give KL = 0 on-policy RL.
determinismkernels
Stabilizing MoE Reinforcement Learning by Aligning Training and Inference Routers
Ma et al. · 2025
Rollout Routing Replay (R3): reuse inference expert choices in training to halve MoE mismatch.
MoEmismatch
DeepSeek-V3.2: Pushing the Frontier of Open Large Language Models
DeepSeek-AI · 2025
Scaled GRPO with off-policy sequence masking, Keep Routing, Keep Sampling Mask; 1,800+ agent environments; RL budget >10% of pretraining.
recipeagents
DAPO: An Open-Source LLM Reinforcement Learning System at Scale
Yu et al. · 2025
Dynamic sampling, overlong filtering and soft overlong punishment: the curriculum and truncation defaults many recipes inherit.
curriculumtruncation
R2E-Gym: Procedural Environments and Hybrid Verifiers for Scaling Open-Weights SWE Agents
Jain et al. · 2025
8.7k procedurally built executable SWE environments; hybrid verifiers beat either kind alone.
environmentsSWE
Training Software Engineering Agents and Verifiers with SWE-Gym
Pan et al. · 2024
The first open training environment of real, executable Python issues.
environmentsSWE
Group-in-Group Policy Optimization for LLM Agent Training
Feng et al. · 2025
Critic-free step-level credit assignment by grouping actions taken from the same environment state.
agentscredit
Recent Frontier Models Are Reward Hacking
Von Arx, Chan, Barnes · 2025 · METR
Concrete o3 exploits (timer overwrites, reading the scorer's answer) and how little prompting helps.
reward hackingevals
Claude 3.7 Sonnet System Card
Anthropic · 2025
§6, "Excessive Focus on Passing Tests": an early, explicit system-card account of RL-induced test special-casing, how it was detected, and its mitigations.
Anthropicreward hacking