Batch Invariance and Numerical Reproducibility
Temperature zero does not give the same answer twice, and the reason is neither random seeds nor GPU atomics; it is that reduction kernels change their split strategy with batch shape, so your logits depend on which other requests happened to be in flight.
Sample the same prompt 1,000 times from Qwen3-235B-A22B at temperature 0 and you get 80 distinct completions, with the first divergence appearing at token 103 (He and Thinking Machines Lab, 2025, Defeating Nondeterminism in LLM Inference). Greedy decoding is deterministic by definition, so the nondeterminism is upstream of sampling: the logits themselves differ between runs.
The usual explanation is wrong
Floating-point addition is not associative, and GPUs are concurrent, so the standard story blames atomicAdd, whose accumulation order depends on thread scheduling. It is a good story about a mechanism that is barely present here. A typical LLM forward pass contains no atomic adds; run the identical kernel on the identical batch twice and it produces bit-identical output.
The real dependency is on shape. GPU kernels pick a parallelisation strategy from the input dimensions, and that strategy determines the order of the summations inside. A matmul with batch 1 splits its reduction differently from the same matmul at batch 32; RMSNorm picks a different rows-per-block; attention chooses a different split over the KV length. Different summation order, different rounding, different low-order bits. This is the property called batch invariance, and the ordinary kernel does not have it.
Why that leaks into your request
A server batches continuously. Your request is processed alongside whichever other requests arrived in the same window, so the batch shape it sees is a function of unrelated traffic. Nothing about your request changed; the reduction order did. The last few bits of a logit shift, two candidate tokens that were within \(10^{-6}\) of each other swap rank, and from that token forward the sequences diverge completely. In the Qwen3 experiment 992 of 1,000 samples continued with "Queens, New York" and 8 with "New York City", from one flipped comparison.
Making kernels batch-invariant
The fix is to fix the reduction order independent of shape, which means giving up the autotuner's freedom.
For attention the important detail is a fixed split size rather than a fixed split count. Splitting a KV cache into a constant number of chunks makes chunk size depend on sequence length, so the reduction tree changes as the cache grows during decoding. Splitting into constant-size chunks, a 1,000-element cache becoming three 256-element chunks plus one of 232, keeps each element's accumulation path the same regardless of how many query tokens are in flight.
The cost is real and has been measured twice. Thinking Machines report an unoptimised deterministic vLLM at 55 seconds against 26 for the default on a 1,000-sequence Qwen3-8B benchmark, improving to 42 seconds with a better attention kernel. SGLang's independent implementation across FlashInfer, FlashAttention 3, and Triton backends reports an average 34.35% slowdown, ranging from 24.4% to 55.1%, and restores single-output determinism where uncontrolled runs produced up to 18 distinct outputs across prefix lengths (LMSYS, 2025, Towards Deterministic Inference in SGLang).
When it breaks
Batch invariance is not the same as cross-configuration invariance. A kernel invariant to batch size can still change its answer when tensor-parallel degree changes, because the reduction is then split across devices differently. That is a separate fix, addressed by reduction trees whose shape is independent of TP size (Zhang et al., 2025, arXiv:2511.17826).
Framework-level determinism flags do not cover this. torch.use_deterministic_algorithms(True) selects deterministic implementations where they exist and errors where they do not, and on CUDA 10.2 and later cuBLAS needs CUBLAS_WORKSPACE_CONFIG set to :4096:8 or :16:8 as well. All of that gives run-to-run determinism at fixed shape. None of it gives invariance across shapes, which is the property that actually breaks in a server.
The reason to care beyond reproducibility is on-policy reinforcement learning. If the sampler and the trainer compute different logprobs for the same tokens, training that was meant to be on-policy is quietly off-policy, and the importance-weighting correction that hides it can fail. With batch-invariant kernels the KL divergence between sampler and trainer stays flat at zero, against roughly 0.001 under off-policy correction; without any correction, a run collapsed in reward around step 318.
14 flashcards for this concept
Click a card to reveal the answer.