简介:温度设为0仍输出不同,原因常在于并发执行与浮点加法不满足结合律。本文从定义出发,拆解确定性推理的含义、误差来源与放大机制,说明其对调试、评测与复现的影响,并给出排序固定、规约顺序确定等工程化应对思路,帮助读者建立可复现的推理系统认知。
在调用大语言模型时,一个常被忽略却反复出现的现象是:即便把采样温度设为 0、关闭随机采样,同一个提示词多次输入,得到的输出仍可能不一致。这种现象通常被称为”确定性输出失效”或”推理不可复现”。它并非模型本身在”随机思考”,而是推理执行链路中并发调度与浮点运算特性共同作用的结果。本文围绕这一概念展开,说明它是什么、为什么发生、如何理解其影响,以及工程上如何应对。
确定性输出失效,指的是在推理参数(如温度、top-p、随机种子)完全固定的前提下,模型对相同输入未能产生逐字节相同输出的现象。
从使用视角看,它表现为”同问不同答”;从技术视角看,它意味着计算图在执行过程中引入了非确定性因素,使最终 logits 或生成 token 序列发生偏移。需要强调的是,温度设为 0 时,采样退化为贪心解码,即每步取 logits 最大值的 token,理论上应完全确定。因此,出现差异说明非确定性并非来自采样环节,而是来自前向计算本身。
在多数闲聊场景中,输出的细微差异无伤大雅。但在以下场景中,确定性是可复现性的基础:
因此,理解确定性输出失效的成因,是构建可信推理系统的一部分。
在 CPU 侧的多线程矩阵乘法中,常见做法是把输出行或分块分配给多个线程并行计算。每个线程从全局原子计数器领取任务分块,计算局部内积并累加到私有缓冲区,最后在临界区内把局部结果合并到全局结果。
问题在于:不同线程领取分块和获取锁的顺序,取决于硬件调度与执行时序,并不固定。于是,N 个局部向量被按照某种随机顺序做归约(reduction),例如:
res = 0 + (p[0] + p[1] + (p[2] + p[3])) + ...
顺序一变,累加结构就变。
单精度浮点加法存在舍入误差,且不满足结合律,即:
((a + b) + c) ≠ (a + (b + c))
当参与累加的分量量级差异较大时,先加小值还是先加大值,会得到不同的舍入结果。因此,归约顺序的随机化直接导致数值结果出现微小偏差。
单步的偏差可能只在末位比特级别,但自回归生成是逐 token 迭代的过程。前面 decode step 的微小 logits 偏差,可能改变某个 token 的选择,进而改变后续所有输入的上下文,使轨迹逐渐分叉。这就是”微小偏差被逐 step 放大”的机制。
除 CPU 多线程外,卸载到加速器上的层也可能存在类似的归约顺序不确定性。即便 CPU 侧已固定顺序,整体输出仍可能变化,说明非确定性来源可能是多处的。
以一个简化流程说明非确定性的产生路径:
输入 prompt→ 嵌入层→ 逐层前向计算├─ 矩阵乘法:多线程分块,归约顺序随机├─ 浮点累加:舍入误差随顺序变化└─ 激活与归一化→ 输出 logits→ 贪心取 argmax→ 生成 token,追加到上下文→ 重复上述过程
关键点在于:矩阵乘法的并行归约是”顺序敏感”的环节。若把该环节改为固定顺序,例如按线程编号轮流排队、固定分块领取与合并次序,则多次运行可得到一致结果。
确定性输出失效,是指在推理参数固定的情况下,因并发调度导致浮点归约顺序随机、进而因浮点加法不满足结合律而产生数值偏差,并沿解码步放大的现象。它不是采样问题,而是执行层面的工程特性。理解其定义与成因,有助于在调试、评测与运维中正确设定预期,并通过固定归约顺序、排查异构算子等手段提升可复现性。对于追求稳定复现的推理系统,确定性应被视为一项需要显式设计与验证的工程属性。