作者/机构: Raja Gond (Microsoft Research), Aditya K Kamath (University of Washington), Arkaprava Basu (Indian Institute of Science), Ramachandran Ramjee (Microsoft Research), Ashish Panwar (Microsoft Research)
核心问题与研究目标
大型语言模型(LLM)的推理过程存在一个关键挑战:非确定性。即使用户使用相同的提示、解码参数和硬件,在不同运行中也可能得到不同的输出。这种系统层面的非确定性源于浮点数运算的非结合性,加之动态批处理(dynamic batching)和GPU核心(kernel)会根据批次大小改变其归约顺序(reduction orders)。一个直接的解决方法是禁用动态批处理,但这会严重降低吞吐量。另一种方法是使核心计算具有批次不变性(batch-invariant),但这将确定性与核心设计紧密耦合,需要新的实现,并会强加固定的运行时开销,无论工作负载中多大比例真正需要确定性。
创新点与解决方案
受推测解码(speculative decoding)思想的启发,本文提出了LLM-42,一种基于调度的LLM确定性推理方法。其核心观察是:如果一个序列处于一致状态,即使采用动态批处理,下一个生成的token也很可能是一致的。此外,大多数GPU核心使用形状一致(shape-consistent)的归约。基于这些洞见,LLM-42采用非确定性的快速路径(fast path)来解码token,并通过一个轻量级的“验证-回滚”(verify–rollback)循环来强制实现确定性。
该方法的工作流程如下(如图1所示):
1. 解码(Decode):使用标准的、高吞吐量的自回归解码(快速路径)生成候选输出token。这些token在大多数情况下是一致的,但无法保证。
2. 验证(Verify):验证器在一个固定形状的归约调度下,重放(replay)候选token。这提供了一个确定性的参考执行。
3. 提交/回滚(Commit/Rollback):验证器提交那些被保证在多次运行中一致的token,并回滚那些违反确定性的token,从上一个已知的一致状态恢复解码。
与传统推测解码的对比如下表所示:
Table 1: 推测解码 vs. LLM-42。
为了平衡验证开销和回滚成本之间的权衡,本文引入了分组验证(grouped verification):将多个请求的小窗口(例如,每个请求32个token)组合在一起进行验证,既保持了小窗口较低的回滚成本,又通过分摊开销降低了验证成本。
主要贡献列表
* 首次对批次不变性计算进行了系统性分析,突出了该方法的性能和工程成本。
* 提出了LLM-42,一种在LLM推理中实现确定性的替代方法。
* 在SGLang之上实现了LLM-42,并证明其开销与需要确定性的流量比例成正比。当确定性流量较低时,它能保持接近峰值的性能,而SGLang在确定性模式下会产生高达56%的高额开销。
图 1: LLM-42 概览。
本节介绍LLM、解释LLM推理中非确定性的来源,并量化基于批次不变性计算的确定性推理的成本。
Transformer架构与推理过程。基于Transformer的LLM由一系列相同的解码器块堆叠而成,每个块包含一个自注意力模块、一个前馈网络(FFN)、归一化层和通信原语(如图2所示)。每个token的隐藏状态顺序流经这些块,但在每个块内部,计算是高度并行的:注意力模块对键值(KV)缓存执行矩阵乘法,FFN在非线性激活函数前后应用两个大型通用矩阵乘法(GEMM),归一化则对隐藏维度进行逐token的归约操作。推理过程分为两个阶段:预填充(prefill)和解码(decode)。预填充阶段并行处理提示(prompt)中的token,为所有输入token生成KV缓存,此阶段以大规模并行计算为主。解码阶段是自回归的:每一步消耗最新的token,用一个新的键和值更新KV缓存,并产生下一个输出token。因此,解码在单个序列内是顺序的,但在批次中的不同请求之间是并行的。
图 2: LLM的高层架构。
非确定性的根源。在有限精度下,像累加这样的算术运算是非结合的,即 $(a + b) + c \neq a + (b + c)$。LLM推理中的非确定性源于这种非结合性与动态批处理(dynamic batching)的结合,后者是实现高吞吐量推理的标准技术。在动态批处理下,同一个请求在不同运行中可能与不同的请求集共同处理,导致批次大小变化。此外,GPU核心会根据输入大小调整其并行化策略,从而改变其归约(reduction)策略。因此,相同的逻辑运算会因为其所在的批次不同而采用不同的浮点数累加顺序,导致不一致的数值结果。
归约操作在LLM中的普遍性。归约在LLM推理中很常见,出现在矩阵乘法(GEMM)、注意力、归一化和诸如AllReduce的集体通信中。GEMM是最常见且耗时最长的算子。高性能的GPU GEMM实现采用分层切片(hierarchical tiling)和并行归约来提高占用率和内存复用。一个常见的优化是split-K并行,即将归约维度划分给多个线程块。每个块计算一个部分结果,然后通过一个额外的归约步骤合并。是否使用split-K以及选择多少个split,取决于输入矩阵的形状。如图3所示,这些选择直接改变了归约树,导致同一token在不同运行中产生不同的数值结果。同样,注意力核心将工作沿键值维度划分以增加SM利用率,随后通过归约合并部分结果。归一化算子则沿特征维度进行归约。随着推理的进行,这些算子中依赖于批次的归约选择会引入微小的数值漂移,这些漂移会跨核心、层和解码步骤传播,最终即使在采样超参数固定的情况下也会影响输出token。
图 3: GEMM核心使用标准累加或split-K并行化计算点积。虽然split-K增加了并行性,但它会根据K的大小改变归约树。
批次不变性计算。He等人【14, Defeating nondeterminism in llm inference, 2025, Thinking Machines Lab Blog, https://thinkingmachines.ai/blog/defeating-nondeterminism-in-llm-inference/】最近提出了一种名为批次不变性计算 (batch-invariant computation)的新方法来实现确定性LLM推理。该方法中,GPU核心被限制为对所有token使用单一、通用的归约策略,从而消除了依赖于批次的归约。SGLang和VLLM都采用了这种方法【32, Towards deterministic inference in sglang and reproducible rl training, 2025, SGLang Blog, https://lmsys.org/blog/2025-09-22-sglang-deterministic/】 【39, Batch invariance, 2025, vLLM Docs, https://docs.vllm.ai/en/latest/features/batch_invariance/】 【40, Deepseek-v3 batch invariant on 8xh100, 2025, vLLM Pull Request, https://github.com/vllm-project/vllm/pull/26609】:这些系统要么部署He等人提供的批次不变性核心 【23, Batch invariant ops, 2025, Thinking Machines GitHub】,要么实现新的核心【31, Support deterministic inference with batch invariant ops, 2025, SGLang Pull Request】【37, Batch-invariant inference, 2025, vLLM Pull Request】。
批次不变性计算的弊端。尽管批次不变性计算能消除非确定性,但我们发现它不适合实际的LLM服务系统。通过强制所有执行采用通用的归约策略,它将确定性与核心设计耦合,并牺牲了性能机会。它还将确定性变成每个请求都必须支付的固定税:动态批处理聚合了请求,但批次不变性核心却消除了使批处理有效的优化——如split-K和形状感知切片(shape-aware tiling)。更糟糕的是,由于大多数核心本身不是批次不变的,采用这种方法需要为确定性维护一个并行的核心栈。我们还量化了这种方法的性能成本。
GEMM性能对比。图4a比较了PyTorch中使用的基于cuBLAS的GEMM与He等人开发的基于Triton的批次不变性核心的吞吐量。矩阵维度对应Llama-3.1-8B-Instruct模型前馈网络的下投影操作。在我们的GPU上,cuBLAS(通过torch.mm)最高达到527 TFLOPS,而批次不变性核心峰值为194 TFLOPS,性能下降了63%。这种差距是因为基于Triton的批次不变性实现没有使用split-K,也没有利用更新的硬件特性,如Tensor Memory Accelerators【2, CUTLASS Tutorial: Mastering the NVIDIA® Tensor Memory Accelerator (TMA), 2024, Colfax Research Blog, https://research.colfax-intl.com/tutorial-hopper-tma/】或 像warp specialization【33, Flashattention3: Fast and accurate attention with asynchrony and lowprecision, 2024, arXiv】这样的先进技术,而PyTorch通过供应商优化的cuBLAS核心利用了所有这些特性。
RMSNorm性能对比。图4b比较了三种RMSNorm实现(SGLang中使用的Python版本、Thinking Machines的Triton核心和SGLang的默认CUDA核心)在不同token数量下的执行时间。前两者是批次不变的;CUDA核心则不是。Python实现比非批次不变的CUDA核心慢高达7倍,原因是未融合的原始操作和共享内存利用率低。Triton核心性能好得多,但仍比融合的CUDA实现慢高达50%,后者得益于优化的归约和核心融合。这些开销在高批次大小或长上下文长度时会被放大,此时归一化可能占推理时间的相当一部分【13, Tokenweave: Efficient compute-communication overlap for distributed llm inference, 2025, arXiv】。
图 4: 批次不变性与非批次不变性核心的性能比较。
端到端吞吐量。图5测量了三种场景下的token生成吞吐量(tokens/秒):(1) 10个请求以非确定性模式运行,(2) 11个请求以非确定性模式运行,(3) 11个请求以确定性模式运行,但只有一个请求需要确定性输出。当有10个并发的非确定性请求时,系统生成845 tokens/s。当一个新请求到达,批次大小增至11时,如果继续非确定性解码,吞吐量提升至931 tokens/s(约增长10%)。相反,如果新请求需要确定性,整个批次被迫通过较慢的批次不变性核心执行,导致吞吐量骤降56%至约415 tokens/s——为了一个确定性请求而惩罚了所有正在处理的请求。这种行为是不可取的,因为它将所有请求的性能与最慢请求的性能耦合在一起。
总结。总的来说,这些结果表明批次不变性执行会带来巨大的性能损失。虽然有可能提高批次不变性核心的性能,但这需要大量的模型和硬件特定的核心开发。这种工程和维护负担使得该方法在实践中难以持续。这可能就是为什么确定性推理目前主要局限于调试和验证,而不是用于实际的LLM服务。
图 5: 不同场景下的解码吞吐量。
本节提炼了一组关于非确定性、GPU核心和LLM用例的具体观察。这些观察揭示了为什么批次不变性计算过于严格,并为一种更通用的LLM推理确定性方法提供了动机。
观察1 (O1):序列处于一致状态时,下一个token通常也是一致的,但一旦出现分歧,自回归解码会逐步放大差异。token变得不一致,仅当浮点数漂移大到足以改变采样器的有效决策时才会发生——例如,通过改变解码器采样策略(如贪婪或随机采样)下高概率候选者的相对顺序或接受度。实践中,这类跨越决策边界的事件很少见,因为数值漂移通常只轻微扰动logits。然而,自回归解码会放大哪怕是单个这样的偏差:一旦一个token不同,所有后续的token都可能分歧。由于单个请求通常产生数百到数千个输出token,即使最初的分歧是由不同归约顺序引起的单个token翻转造成的,两个序列级别的输出也可能看起来截然不同。
实验验证O1。为了凭经验证明这一现象,我们使用Llama-3.1-8B-Instruct模型在ShareGPT数据集上进行了一个实验。我们首先以批次大小为1(即没有动态批处理)执行350个请求,以获得参考(“基准”)输出token。然后,我们在负载为每秒6个查询的动态批处理下重新运行相同的请求,并将每个请求的输出与其参考值进行比较。在两次运行中,我们都将输出长度固定为512个token。
分歧量化指标。我们使用两个指标来量化分歧。请求的第一个一致跨度(first consistent span)衡量两次运行中初始输出token完全匹配的数量,而第二个一致跨度(second consistent span)衡量第一个和第二个分歧点之间匹配的token数量。图6显示了80个请求的这些指标。在通常情况下,数百个初始token在两次运行中是相同的,有些请求在第一个一致跨度中所有512个token都完全匹配。然而,一旦单个token出现分歧,序列就会迅速漂移:大多数请求的第二个一致跨度接近于零,表明分歧迅速传播到输出的其余部分。
图 6: 不同请求在动态批处理下,第一个和第二个一致跨度(与基准匹配的token数量)的长度。
观察2 (O2):大多数GPU核心使用统一的、形状一致的归约。它们对给定批次内的所有元素应用相同的归约策略。此外,该策略对于所有相同形状的批次都保持不变,仅在形状改变时才改变。
位置不变性。最简单的例子是GEMM核心。对于一个给定大小为 M x K 的输入矩阵 A,GEMM核心会对所有 M 个输入元素采用相同的归约顺序(比如 R)。此外,它会对所有大小为 M x K 的输入矩阵应用相同的归约顺序 R。我们将这类核心称为位置不变的(position-invariant)。位置不变性意味着,在总批次大小固定的情况下,一个输入元素的输出与其在批次中的位置无关。图7展示了一个位置不变性核心的例子,表2显示了常见LLM算子的不变性属性。
位置不变性与批次不变性。批次不变性计算的动机源于LLM中使用的GPU核心虽然对于特定输入是确定性的,但不是批次不变的。我们观察到,位置不变性捕捉了一个比确定性更强的属性:确定性只要求相同的输入在不同运行中产生相同的输出,而位置不变性意味着只要核心的输入大小保持不变,给定输入的输出就保持一致。这使我们能够在输入形状的层面上推理核心行为,而不是单个输入值。
图 7: 一个位置不变的核心,对于给定的输入元素,只要总批次大小固定,无论其在批次中的位置如何,都会产生相同的输出。在这个例子中,如果核心是位置不变的,则 T' == T''。
Table 2: 常见推理算子的不变性属性 (‡num_splits=1, ∗CUDA 13.0+, ⋆特定NCCL设置, †vLLM/SGLang默认值)。
观察3 (O3):对于确定性推理,只需确保给定token位置在请求的所有运行中经历相同的归约策略即可;序列内部或跨序列的不同token位置的归约策略可以不同。一个token输出的数值差异来自于其自身的浮点数归约是如何执行的,而不是来自其他共同批处理token的数值。虽然批处理影响计算的调度和分组方式,但给定token位置的计算在功能上是独立的:它消耗相同的输入并执行相同的操作序列。因此,token之间的交互仅通过执行选择(例如哪些部分和被一起归约)间接发生,而不是通过直接的数据依赖。因此,只要一个token位置总是使用相同的策略进行归约,其输出就会保持一致,无论其他token位置如何计算。
观察4 (O4):当前系统采取全有或全无的方法:要么为每个请求强制确定性,要么完全禁用它。这种设计不自然地适用于LLM部署。这是因为许多LLM工作负载既不需要按位复现,也无法从中受益。实际上,受控的随机性通常是可取的,因为它增强了LLM的输出多样性和创造性【17, Stochastic chaos: Why deterministic inference kills, and distributional variability is the heartbeat of artifical cognition, 2026, arXiv】【19, A comprehensive analysis of large language model outputs: Similarity, diversity, and bias, 2025, arXiv】【44, Integrating randomness in large language models, 2024, arXiv】。相比之下,像评估运行、安全审计或回归测试等请求需要位级别的可复现性。总的来说,不同用例意味着为所有请求强制确定性是矫枉过正。
全有或全无行为的根源。值得强调的是,这种全有或全无的行为主要源于将确定性与核心设计绑定的批次不变性方法。由于所有共同批处理的token都通过同一组核心,确定性成为批次的全局属性,而不是可选择的。虽然可以为不同请求运行独立的确定性和非确定性核心,但这会分割批次、复杂化调度,并可能损害效率。
由于LLM推理中的非确定性来自动态批处理,禁用它将使推理变得确定性。然而,动态批处理可以说是LLM推理中最强大的性能优化【4, Sarathi: Efficient llm inference by piggybacking decodes with chunked prefills, 2023, arXiv】【20, Efficient memory management for large language model serving with pagedattention, 2023, SOSP】【42, Orca: A distributed serving system for Transformer-Based generative models, 2022, OSDI】【46, DistServe: Disaggregating prefill and decoding for goodputoptimized large language model serving, 2024, OSDI】。因此,我们的目标是在存在动态批处理的情况下实现确定性。本节,我们介绍一种受推测解码启发的、由调度器驱动的方法LLM-42来实现这一目标。
利用观察结果。LLM-42利用§3中提出的观察如下:
* 利用O1:由于从一致状态解码的token大多是一致的,我们重新利用推测解码风格的机制,通过一个解码-验证-回滚(decode–verify–rollback, DVR)协议来强制实现确定性。DVR使用快速路径乐观地解码token,并由一个验证器确保确定性。只有经由验证器批准的token才会返回给用户,而少数验证失败的token则被丢弃并重新计算。关键在于确保验证器自身的输出总是一致的。我们利用O2来实现这一点。
* 利用O2:因为GPU核心依赖于形状一致的归约,我们通过让验证器始终操作固定数量的token(例如,一次验证10个token)来使其确定性。唯一的边界情况发生在序列末尾,此时可能剩下少于T个token(例如,第11个token是序列结束token)。我们通过用虚拟token填充来处理这种情况,以便验证器总是处理恰好T个token。
* 利用O3:确定性只要求每个token位置在不同运行中遵循一致的策略,而不同位置可以遵循不同策略。这一观察让我们能够用不同的策略计算预填充和解码阶段。因为预填充即使在单个请求内也是大规模并行的,所以通过避免预填充token的任意批处理,可以使其变得确定性,从而在该阶段无需验证器。验证器仅对解码阶段生成的token是必需的。
* 利用O4:LLM-42通过将确定性移至一个独立的验证阶段,从而将其与token生成解耦。这使得选择性确定性变得简单:只有需要确定性推理的请求才会产生验证开销,而所有其他流量都避免了它。我们通过一个新的API标志is_deterministic=True|False向用户暴露此控制,允许他们按请求明确要求确定性;默认为False。
选择性确定性的性能优势。图5量化了选择性确定性的性能优势。当11个请求中有一个需要确定性时,LLM-42实现了911 tokens/秒的解码吞吐量,这比SGLang的确定性模式吞吐量高2.2倍,并且仅比非确定性模式(最佳情况)的吞吐量低3%。我们将在§5中提供更详细的评估。
DVR工作机制。DVR通过首先使用高吞吐量、非确定性执行生成token,然后通过验证和重新计算来纠正任何不一致性,从而乐观地进行解码。它不是预先强制确定性,而是在运行时识别生成序列中的不一致性,并仅重新计算那些不能保证在给定请求的所有可能运行中都一致的token。
图示说明。图8说明了DVR的操作方式,假设验证窗口为四个token。蓝色请求需要确定性输出,其第一个输出token T0由确定性的预填充阶段产生,该阶段避免了任意的请求间批处理。然后,LLM-42使用常规的快速路径和动态批处理生成候选token T'1、T'2和T'3,其中灰色请求可以任意批处理。验证器的第一个输入应该是一致的(在本例中,T0是一致的,因为它来自预填充阶段)。验证器将这四个token T0和T'1–T'3作为输入进行重放,并产生输出token T1–T4。验证有两个可能的结果:(1) 所有token通过验证,或(2) 一个或多个token验证失败。我们下面详细描述这两种情况。
情况1:验证成功。在常见情况下,验证会重现前序解码迭代生成的相同token。例如,在图8a中,T1 = T'1, T2 = T'2, T3 = T'3。在这种情况下,LLM-42接受所有这些token;此外,它还接受token T4,因为T4是由验证器从一个一致状态生成的,因此也是一致的。
情况2:验证失败。偶尔,验证过程会与一个或多个解码的token不一致,例如,在图8b中,只有T'1与验证器的输出匹配。在这种情况下,LLM-42只提交输出到最后一个匹配的token(T'1);所有后续的token(T'2和T'3)都被拒绝。在最后一个匹配位置(T2)之后紧接着出现的验证器生成的token也被接受,并且KV缓存在此位置被截断。下一次解码迭代从这个修复后的一致状态恢复。
保持KV缓存一致。在解码阶段,KV缓存由在动态批处理下执行的快速路径迭代填充。因此,即使token验证成功,对应于已验证窗口的KV缓存仍可能不一致,因为它是由非确定性执行产生的。这种不一致性可能会影响未来迭代中生成的token,尽管当前窗口已经过验证。因此,仅进行token级别的验证是不够的,还需要修复KV缓存。为了解决这个问题,我们用验证过程中相应的条目覆盖解码期间产生的KV缓存条目。这确保了发出的token和KV缓存状态对于后续的解码迭代都是一致的,从而消除了下游的分歧。
保证前向进展。请注意,每次验证过程至少会产生一个新的一致输出token,如图8所示。因此,即使在可能为每个乐观生成的token触发回滚的人为最坏情况下,DVR也能保证前向进展。在我们的实验中,我们没有观察到任何此类情况。
与推测解码的对比。总的来说,DVR遵循推测解码的高层结构,但在几个重要方面有所不同,如表1所述。在DVR下,解码的token是模型前向传递的忠实执行结果,偏差仅源于浮点舍入误差。相比之下,推测执行技术使用修改过的前向计算生成候选token——例如,通过运行一个更小或蒸馏的草稿模型【22, Fast inference from transformers via speculative decoding, 2023, ICML】【25, Specinfer: Accelerating large language model serving with tree-based speculative inference and verification, 2024, ASPLOS】或通过截断或修剪注意力/上下文【8, Medusa: Simple llm inference acceleration framework with multiple decoding heads, 2024, ICML】【12, Break the sequential dependency of llm inference using lookahead decoding, 2024, ICML】。由于这些近似改变了计算本身,推测深度通常被限制在少数(2-8)个token【8, Medusa: Simple llm inference acceleration framework with multiple decoding heads, 2024, ICML】【12, Break the sequential dependency of llm inference using lookahead decoding, 2024, ICML】【22, Fast inference from transformers via speculative decoding, 2023, ICML】【25, Specinfer: Accelerating large language model serving with tree-based speculative inference and verification, 2024, ASPLOS】。相反,利用O1,DVR可以安全地在更长(32-64)的token序列上进行推测。出于同样的原因,DVR中的验证成功率很高,与现有推测解码方案中观察到的低得多的接受率形成对比。最后,DVR使用相同的模型进行验证,而大多数推测解码方法需要一个独立的模型进行验证。
图 8: 解码-验证-回滚示例。通过常规解码生成固定数量的token后,LLM-42通过一个独立的前向传递并行验证它们。(a) 解码阶段生成的所有token都通过了验证;LLM-42接受所有这些token以及新的由验证器生成的token (T4)。(b) 解码和验证之间的一些token不匹配;LLM-42只接受初始匹配的token (T'1)和随后的验证器生成的token (T2);所有其他token都被重新计算。在这两种情况下,验证器都会用自己的KV缓存条目替换解码阶段生成的条目。
验证窗口大小的权衡。DVR的效率取决于验证窗口的大小,并涉及一个权衡:较小的窗口会产生较高的验证成本但重新计算开销较低,而较大的窗口会降低验证成本,但以增加重新计算为代价。我们通过在H100-PCIe GPU上对Llama-3.1-8B-Instruct进行性能分析,凭经验表征了这种权衡。我们根据验证前向传递的延迟来测量每个token的验证成本。为了量化重新计算成本,我们在在线设置中以每秒12个查询的速度执行来自ShareGPT数据集的4096个请求。对于每个窗口大小,我们测量解码的总token数与返回给用户的token数;两者之差表示重新计算开销。
实验结果分析。图9a显示了每个token的验证成本随验证窗口大小的变化。对于较小的窗口,验证过程是内存受限的:每个token执行的计算很少,导致算术强度低和硬件利用率差。因此,验证成本很高——每个token高达0.75毫秒。随着验证窗口的增加,核心过渡到计算受限,每个token的成本急剧下降,在窗口大小为512时达到0.05毫秒,下降了15倍。图9b显示,超过一半的请求完成时没有任何回滚(即它们的所有输出token都通过验证),而一小部分请求会频繁发生回滚。此外,随着窗口大小的增加,回滚变得更加普遍。例如,窗口大小为256时,约40%的请求观察到50%或更高的回滚率,表明至少一半的验证步骤检测到一个或多个不匹配的token。相比之下,窗口大小为32时,只有约5%的请求达到此水平。每个请求重新计算的token数也遵循相同的趋势,如图9c所示。此外,图9d显示了由此产生的总重新计算开销。请注意,验证失败需要重新计算当前窗口内不匹配位置之后的所有token。因此,平均而言,较大的窗口会产生较高的重新计算开销。具体来说,窗口大小为32时,重新计算开销为6.81%,并大致呈线性增加,在窗口大小为256时达到46.41%。
分组验证。我们提出分组验证(grouped verification)来解决验证成本和重新计算成本之间的固有权衡。我们不是验证单个请求的大窗口(256个token),而是在一次传递中共同验证多个请求的小的、固定大小的窗口(例如,8个请求,每个32个token)。这样,每个请求都保留了小窗口的回滚属性,而验证过程则在大的有效批次上操作,实现了高利用率和低验证成本。
图 9: 不同窗口大小下验证和重新计算的成本。
确保端到端确定性。保证确定性要求推理管道中的每个算子都表现出一致的行为。本节强调了常用算子中一些细微的不一致性来源。我们在此不引入新技术;相反,我们采用已有的方法来强制执行一致的行为,并为完整性起见进行总结。
注意力机制。注意力涉及多个步骤的归约:沿序列维度的归约(例如,在FlashDecoding风格的序列并行中【11, Flash-Decoding for long-context inference, 2023, Stanford CRFM Blog, https://crfm.stanford.edu/2023/10/12/flashdecoding.html】)和softmax计算内部的归约。为了使其一致,我们使用FlashAttention-3注意力核心,并在验证过程中将KV拆分的数量设置为1;快速路径的解码迭代照常运行 。
通信集合操作。经典的基于环(ring-based)的AllReduce根据token在批次中的位置以不同顺序进行归约。相比之下,CUDA 13.0中引入的基于multimem的AllReduce遵循一致的归约调度【38, Same data all reduce on h20, but results are different, 2025, vLLM GitHub Issue】,因此在支持的情况下应优先使用。在不支持multimem/NVLS的旧平台上,可以使用具有固定NCCL配置的基于树(tree-based)的AllReduce(例如,将num_channels设置为1并使用固定协议)来实现确定性,但代价是比基于环的AllReduce更高的通信成本。
采样。我们采用SGLang的采样器。当温度为零时,它选择logit最高的token(argmax),如果存在多个最大值,则返回第一个最大值的索引。然而,对于非贪婪采样,采样过程涉及随机性,使得输出对随机数的生成和使用方式敏感。为了解决这个问题,SGLang引入了一个新的采样函数multinomial_with_seed,它取代了torch.multinomial,后者在批处理执行下本质上是一个非确定性算子。该函数用从种子哈希函数生成的Gumbel噪声扰动logits,确保相同的输入-种子对总是产生相同的样本【32, Towards deterministic inference in sglang and reproducible rl training, 2025, SGLang Blog, https://lmsys.org/blog/2025-09-22-sglang-deterministic/】 。
总结。总的来说,在整个推理管道中强制确定性需要仔细配置注意力核心并选择合适的AllReduce实现。采样模块确实需要新的实现,但这是一次性成本,因为所有模型都使用相同的采样器。相比之下,LLM系统中性能和工程工作的大部分在于GEMM核心,LLM-42完全重用了这些核心,以及RMSNorm和FusedMoE核心。
Table 3: 数据集及其输入/输出上下文长度。
实验内容: 对8种工作负载配置(ArXiv、ShareGPT及6种不同输入输出长度的配置)进行离线推理,每个配置执行4096个请求,测量吞吐量(tokens/秒)。
实验结果与结论:
* SGLang确定性模式的开销: 如图10所示,在SGLang中启用确定性推理会导致显著的吞吐量损失,范围从24%到36%。这源于批次不变性核心的性能低于标准优化核心。
* LLM-42的性能: 相比之下,LLM-42主要使用常规优化核心,因此吞吐量更高。即使在100%请求需要确定性的最差情况下,LLM-42在除一个配置外的所有配置中都优于SGLang-Deterministic。
* LLM-42的可伸缩性: LLM-42的吞吐量随着确定性请求比例的降低而单调提高。例如,在ArXiv数据集上,当确定性流量分别为5%、10%、20%和50%时,LLM-42的吞吐量分别达到了SGLang-Non-Deterministic(最佳情况)的92%、98%、99%和99%。这表明LLM-42对非确定性请求几乎没有计算开销,在这些场景下比SGLang-Deterministic快高达41%。
* 回滚与重计算开销: 表4报告了LLM-42的回滚次数和重计算token数。结果显示,即使在非平凡的确定性比例下,回滚和重计算开销也很小。在最坏的情况下(ArXiv 100%确定性流量),平均每个请求的回滚次数少于一次,重计算token比例最高为10.97%,而平均情况则低得多。这表明在实践中,回滚频率和重计算成本都是适度的。
图 10: 离线推理中的吞吐量。SGLang只有两种模式:所有请求要么在确定性模式下运行,要么在非确定性模式下运行,而LLM-42支持选择性确定性(图例中的百分比值反映了需要确定性输出的流量比例)。
Table 4: 回滚和重计算统计数据(对8个请求,每个64个token进行分组验证)。重计算成本仅显示在100%确定性流量的列中。
实验内容: 在ShareGPT数据集上,随着负载(QPS)的增加,测量端到端请求执行延迟的CDF和首个token时间(TTFT)。
实验结果与结论:
* 端到端延迟: 如图11所示,在所有QPS下,SGLang-Deterministic的延迟CDF明显右移且有长尾,表明其中位数和尾部延迟都显著更高。LLM-42的延迟曲线紧随非确定性基线,随着确定性流量比例的增加,延迟仅温和增长。在各种负载下,LLM-42都保持了比SGLang-Deterministic更紧凑的CDF和更低的尾部延迟。仅在低QPS且100%请求需要确定性时,由于实现上的瑕疵(全局暂停和非批处理预填充),LLM-42的延迟才高于确定性基线。
* 首个token时间(TTFT): 如表5所示,LLM-42的TTFT也随着确定性流量比例的增加而单调增加,但在低比例下开销适中。即使所有流量都是确定性的,LLM-42的尾部TTFT也远低于SGLang-Deterministic(例如,在18 QPS下,LLM-42的P90 TTFT为101.2毫秒,而SGLang-Deterministic为171.6毫秒)。
图 11: ShareGPT数据集在不同负载下在线推理的请求端到端延迟CDF。
Table 5: ShareGPT数据集在不同负载下的首个token时间(TTFT)延迟。
实验内容: 在ShareGPT数据集上进行消融研究,分析分组验证的两个参数——每个请求的验证窗口大小和一次共同验证的请求数——对性能的影响。
实验结果与结论:
* 无分组验证的影响: 如图12所示,在没有分组验证(批大小为1)的情况下,延迟对窗口大小的依赖呈非单调性。这反映了验证开销(小窗口高)和重计算成本(大窗口高)之间的基本权衡。最佳性能出现在窗口大小为128时。
* 分组验证的效果: 分组验证显著降低了端到端延迟。即使只批处理两个请求,也能大幅降低P99延迟。随着批大小的增加,性能进一步提升。最佳配置是每次验证总共256个token(分布在4、8或16个请求上),均实现了34-35秒的P99尾部延迟。
* 在线与离线重计算成本差异: 实验还发现,在线推理的重计算成本高于离线推理,这归因于在线场景中因负载波动、请求到达和离开时间导致批大小的变异性更大。
图 12: 不同验证策略对端到端延迟(左)和重计算成本(右)的影响。批大小表示共同验证的请求数量。
跨模型和多GPU的评估。尽管本文仅报告了Llama-3.1-8B-Instruct的性能结果,但我们已在多个其他模型上评估了我们方法的正确性,包括Qwen-4B-Instruct-2507、Qwen3-14B和Qwen3-30B-A3B-Instruct-2507,以及在1-4个GPU上使用张量并行。我们当前的实验设置不支持multimem/NVLS,并且仅限于成对的NVLink连接;因此,公平评估多GPU性能需要不同的平台,我们将其留作未来工作。支持这些模型不需要在LLM-42中进行额外的代码更改,这突出了我们方法的简便性。
局限性。在我们的当前原型中,即使选择性地启用确定性,验证过程也会为所有请求引入延迟开销。这个开销可以通过将验证限制在GPU SM的子集上或推迟验证批次(例如,优先处理常规的预填充和解码)来减轻。第二个局限性是,LLM-42中的预填充和解码使用不同的归约策略,使得系统不满足预填充-解码不变性。因此,LLM-42目前不支持在同一请求的多次轮次中共享前缀缓存或在请求之间共享。我们的实现目前也未与基于推测解码的LLM推理集成。解决这些局限性是未来有趣的工作方向。
在LLM推理中实现确定性至今仍然繁琐。现有系统通过强制执行批次不变性计算来实现确定性,这种方法在实践中很麻烦:它需要在硬件和模型架构都在快速发展的时期重写核心。此外,批次不变性核心本质上是次优的,因为它们阻止核心在运行时调整其并行策略。我们提出了LLM-42,这是一个更简单的替代方案,它通过重新利用推测解码来在LLM推理中实现确定性。LLM-42最大限度地减少了编写新核心的需求,并支持选择性地强制执行确定性,仅对实际需要的流量部分产生运行时开销。