正文
Defeating Nondeterminism in LLM Inference
https://thinkingmachines.ai/blog/defeating-nondeterminism-in-llm-inference/ 请你阅读这个url的内容,帮我整理文中的观点,并回答LLM的输出结果能不能复现,确保哪些条件等等
ChatGPT 说:
我读了这篇 “Defeating Nondeterminism in LLM Inference”(Thinking Machines Lab, 2025年9月10日)。下面我整理文中的主要观点,并结合你的问题回答 LLM 输出能不能复现、需要哪些条件。
文章的主要观点整理
- 问题背景:即使设置 temperature=0,也经常不能完全复现一样的输出文中说:即使在“greedy sampling”(温度设为0,总是选最大概率 token)下,或在开源推理库(比如 vLLM 或 SGLang)上,在相同 prompt 下也会得到不同的输出。 Thinking Machines Lab
- 通常被认为的原因:“并发 + 浮点不结合性(non-associativity)”
- 在 GPU 上并行算子(比如多个线程、多个 core)可能导致相同的浮点操作(加、乘等)在不同执行次序中累积,从而因为浮点加法非结合性,产生微小差异。 Thinking Machines Lab+1
- 举例提到:$(a + b) + c \neq a + (b + c)$ 在浮点数(finite precision)下是常见的。 Thinking Machines Lab
- 这还不是全部原因:文章认为很多人把原因归结在“原子加法(atomic add)”或并发中累加顺序不确定性上,但真实的关键部分在“batch 不变性(batch-invariance)”Thinking Machines Lab
- 什么是 batch-invariance
- 批次大小 (batch size)、以及 batch 中元素的位置等,不应该影响某一个样本在推理过程中得到的数值结果。即使其他样本在同一个 batch 中,或者 batch 大小不同,或者并发用户请求数变动,也不影响某一个请求的输出。 Thinking Machines Lab
- 具体地,如果一个 kernel 在不同的 batch 大小/不同的切分策略(splitting tiles, reduction strategy 等)中用不同的算法或执行路径,那么就违反 batch-invariance。 Thinking Machines Lab
- 哪些算子需要特别注意文中指出需要重点处理的操作(kernels)包括:
| 算子(Kernel) | 带有 reduction(归约)性质 / 对 batch size 或切分方式敏感 | 需要保证 batch-invariance 的难点 |
|---|---|---|
| RMSNorm | reduction over hidden dimension | 当 batch size 很小 vs 很大,内部 reduction 的策略可能切换 → 可能不 invariant。 Thinking Machines Lab |
| 矩阵乘法(MatMul) | 点乘 + reduction;还受 tile 分割、split-K 等策略影响 | 若在不同 batch 大小/不同 GPU 核心分配下用不同的策略,则不 invariant。 Thinking Machines Lab |
| 注意力机制(Attention) | 多维 reduction:特征维 + 序列维 + KV 缓存(key/value cache)等 | 更复杂,因为 sequence 长度、KV cache 大小、chunked prefill/slicing 的策略等都会影响 reduction 的执行顺序和切分方式。 Thinking Machines Lab |
- 文章里给出的解决方案:batch-invariant kernels
- 设计和使用那些无论 batch size、sequence 切分情况、KV cache 状态如何,内部 reduction 的顺序 /切分 /线程分派策略都是确定的/一致的。这样确保数值路径在这些维度上不变。 Thinking Machines Lab
- 举例细节:• 对 attention 中的 split-KV 策略做固定大小 split(fixed split-size),而不是固定分片数量,以确保切分方式与 batch size 或当前请求的 tokens 数量无关。 Thinking Machines Lab• 在 vLLM 中借助其 FlexAttention backend + 用 torch.Library 替换 /插入 batch-invariant 的 operators,以让整个推理过程在这些关键 kernel 上变得 batch-invariant。 Thinking Machines Lab
- 实验结果
- 用 Qwen-3 模型,对 prompt “Tell me about Richard Feynman” 用 temperature=0,生成 1000 次输出,每个 1000 tokens。结果在默认情况下,有 80 个不一样的 completion;即使前面有非常长的一段(前 102 token)完全一致,第 103 token 开始就分歧了。 Thinking Machines Lab
- 当用 batch-invariant kernels 后,同样配置下 1000 次输出完全一致。 Thinking Machines Lab
- 性能折中
- 引入 batch-invariant 算子会带来性能(速度/吞吐)损失。文章实验中,用 Qwen-3-8B 模型,默认 vLLM 用时 vs deterministic (未优化) 用时 vs 加上优化 attention kernel 的 deterministic 用时,对比显示:虽然比默认慢不少,但并非不可接受。 Thinking Machines Lab
- 对 RL / Training 的影响
- 在 RL 设置(例如 on policy RL)里,如果推理阶段与训练阶段数值不一致,就会把本来应该是 on-policy 的变成某种 “off-policy” 的误差。文中把 deterministic inference 看为是消除这种误差(在训练 /采样 /推理环节保持 bitwise 相同)的一步。 Thinking Machines Lab
结合你的问题:LLM 输出能不能复现?需要哪些条件才能复现?
输出能不能复现?
- 理论上可以。在非常理想/受控的环境中,设置得当的话:相同模型 checkpoint、相同输入、temperature=0(greedy 解码)、使用 batch-invariant的算子/kernel、相同的硬件 & 软件版本、完全不受外部并发请求/batch size变动影响,是可以 bitwise 一致(每一个 bit 或 token 序列完全相同)的输出。
- 现实中默认是不行的,因为很多环境中并未满足以上所有条件。就算 temperature=0,也常看到在第一个差别处(某个 token)就出现不一样。文章的实验就证实了这一点:在没有特别处理 batch-invariance 的情况下,数百次重复就会在某个 token 出现分歧。 Thinking Machines Lab
必要条件 / 要确保什么才能复现:
下面这些条件在文章里被标明或隐含是必要的:
| 条件 | 说明 |
|---|---|
| 温度设为 0 + greedy 解码 | 不采样,不用 top-k / top-p 等随机策略。 |
| batch-invariant kernels | 所有关键 kernel(矩阵乘法、attention、归约操作如 RMSNorm 等)在不同 batch 大小、不同 sequence 长度/KV cache 状况下,执行路径与 reduction/切分策略相同。 |
| 固定硬件 /软件版本 | GPU 型号、驱动版本、库版本(比如 PyTorch / cuBLAS / CUDA / Triton 或其他 backend)要完全相同。因为不同版本的实现里可能选用不同的 kernel 或者不同的 tile 或算法优化。 |
| 无其他并行/批处理变动 | 推理服务器负载要固定,或者确保每次请求在完全相同的 batch size /排列等环境中处理。不能偶然由于批处理调度、并发用户请求或 batching 导致相同请求在不同 batch 中被处理。 |
| KV cache /prefill /切分策略一致 | 在 attention 的 prefill / decoding 阶段,KV cache 的处理(顺序、切分、masked blocks 等)必须尽量一致。不能一次把 prefill 分块,一次一次性算全;这些不同处理会影响 reduction order。 |
| batch size / position 在 batch 中的位置无影响 | 某一个请求的输出不能因 batch 中其他请求的存在或 batch size 的不同而变化,即 “batch invariance” 要保证。 |
总结
- 如果你满足以上所有条件,那么是可能复现完全一样的响应的(即“完全相同的 token 序列 / bitwise 一致”)。
- 在实际应用中,要达到这些条件成本不低(可能牺牲性能、吞吐、并行度优化等)。
- 默认情况(像用公开 API 或在服务器上推理)很少能保证这些条件,因此输出通常有微小差异。
如果你愿意,我可以帮你写一个“复现实验”的清单(checklist)+一个最简单的 PyTorch + Transformer + batch-invariant kernels 的配置示例脚本,让你在本地验证这一点,要吗?
你说:
最终,帮我回答我的问题,如果我在调用LLM时,temperature=0,topk=1,topp=0.0,是否能实现每次结果一致,为什么
ChatGPT 说:
直接回答你的问题:
如果你在调用 LLM 时设置 **temperature=0, top_k=1, top_p=0.0** ——
1. 理论上
- 这是纯粹的 贪婪解码 (greedy decoding),每一步总是选择概率最大的 token。
- LLM 本质是个确定性的函数:同样输入 → 同样权重 → 同样解码方式 → 结果应该相同。
- 所以在数学上,它应该输出完全一致的结果。
2. 现实中
即使设置成贪婪解码,输出也 不一定完全一致,原因是推理框架和硬件会引入非确定性:
- 浮点精度误差:GPU 并行运算时,累加顺序不同会导致 logits 出现微小差异,进而影响“最大概率 token”的选择。
- 算子实现差异:不同版本的 CUDA/cuBLAS、PyTorch、vLLM 可能在矩阵分块、归约方式上有所不同。
- batch 不变性问题:同一个请求如果被放到不同 batch size 里,可能执行了不同的 kernel 算法 → 得到不同的结果。
- Tie-breaking(并列最大概率):如果两个 token 概率完全相等,有的实现会固定选择第一个,有的会随机选。
3. 什么时候能保证一致
要想真正保证结果完全复现,需要额外条件:
- 使用 确定性算子(如 PyTorch 的
torch.use_deterministic_algorithms(True)或 batch-invariant kernels)。 - 保证 相同硬件和软件版本(GPU 型号、CUDA、cuBLAS、PyTorch/Transformers/vLLM 版本)。
- 保证 每次推理环境一致(同样的 batch size、KV cache 策略、并发情况)。
✅ 最终结论:
- 仅仅设置
temperature=0, top_k=1, top_p=0.0,并不能保证每次结果完全一致。 - 你还需要确保 数值计算的确定性(determinism) 和 batch-invariant 算子,否则在长文本推理时,可能在某个 token 处出现分歧。
- 在短回答 + 同一环境下,大概率能复现;在长回答或高并发环境下,不一定。