跳到正文
原文
Hacker News· gmays·· 23 小时前精选AI 评分54

推测解码为何能提升速度

Why Is Speculative Decoding Fast?

AI 导读

推测解码变快不是因为减少了每个 token 的工作,而是低批量时用更多总 FLOPs 填补 GPU 的空闲算力。小型草稿模型先提出一段 token,大模型在一次前向传播中并行验证,用同一序列的“深度”替代多序列的“广度”。

推荐理由

文章以内存受限和计算受限作对照,解释低批量场景下推测解码用更多总 FLOPs 换取更快生成的原因。

正文 · AI 翻译

这并不是因为你完成的工作量更少,而是因为你改变了 GPU 所执行工作的类型。

人们普遍误以为,投机解码之所以快,是因为每个 token 完成的工作量更少。 仅仅“验证”草稿所需的 FLOPs 就少于生成相同数量的 token。

这种说法并不属实。

投机解码有一件违反直觉的事:你实际上会做更多工作! 对于同一个序列,你执行的浮点运算(FLOPs)总量反而会上升。

但那它为什么快?如果计算效率并不是重点,一个准确的草稿模型究竟能带来什么?

答案在于 GPU 所执行工作的类型。

SpecDec 快速回顾

投机解码是一种技术:你使用一个小型草稿模型生成一个可能的草稿序列,然后用大模型并行验证该序列(通过一次前向传播)。

传统的 LLM 解码每次只处理一个 token:

a decoder LLM taking the prompt tokens "The quick" and emitting a single next token, "brown"

但投机解码让你能够一次查看多个 token,并接受那些本来会由大模型生成的 token:

the decoder LLM verifying three draft tokens alongside the prompt in one pass, accepting "brown" and "fox" and rejecting "hopped" in favor of "jumped"

工作的类型

模型在 GPU 上运行时,会执行不同类型的工作。 显而易见的一类是运行矩阵乘法、点积或其他张量运算。 但另一个重要却不易注意到的工作是:在全局内存与局部内存之间加载数据(以及反向加载)。

当 GPU 等待数据加载以执行某项运算时,我们称其为受内存限制的运算。 如果数据都已加载完毕,但我们正在等待所有张量运算完成,则称其为受计算限制的运算。

(如需对此进行更深入的了解,我之前写过一篇文章:Roofline 模型可视化指南)

当 LLM 每次解码一个 token 时(如图一所示),它非常 受内存限制。 对于每个 token,我们都必須流式读取模型中所有正在使用的参数(例如,Qwen3.5-27B 的 27B 个参数)。 当 LLM 在单个步骤中对数千个 token 进行批量解码(如图二所示)时,它则受计算限制。

five sequences decoding in parallel, T = 5 tokens entering the decoder LLM in a single step and five tokens coming out

当 LLM 解码受内存限制时,你就在浪费算力。 GPU 本可以执行更多运算,但它没有。 例如,如果你解码的是 2 个序列而不是 1 个序列,每个 token 所需的时间也不会增加。

投机解码是一种利用这些闲置算力来加快解码的方法(在批量大小较小时)。

以广度换深度

具体来说,假设一次前向传播中最优的 token 数量为 5。 如果少于这个数量,我们会受内存限制;多于这个数量,则会受计算限制。

我们有两个选择。

第一种,我们可以运行一个包含 5 个序列的批次,每个序列每次解码一个 token。 我们称之为“广度”(跨序列):

the same T = 5 batch, read as breadth: five separate sequences each advancing by one token

另一种,我们可以使用投机解码,在一个序列中运行 5 个,从而为该序列实现较高的“深度”:

T = 5 tokens from a single sequence entering the decoder LLM, with four of the five tokens accepted

在这两种情况下,GPU 执行的工作量大致相同。 第一种情况下,5 个序列都取得少量进展;第二种情况下,我们的一个序列取得大量进展。

如果你增加更多序列,同时仍投机解码到相同深度,你只会因受计算限制而让它们全部变慢。

但在小批量大小下(批量大小 << 最优 token 数量),投机解码让你能够利用“免费”的算力,更快地完成所有序列!

为什么这很重要?

这一切听起来可能有些吹毛求疵。 推测解码确实会在批量大小较小时加快速度,所以就算它需要同样多、甚至更多的算力,那又怎样?

当你开始处理真实世界的负载,或深入研究推测解码时,这一点就变得重要起来。 如果最优批量大小是 5,但我们仍如下图所示启用了推测解码,那么我们实际上是在浪费算力,而这些时间本可以用来搬运内存数据!

five sequences each speculating four tokens deep, T = 20 tokens in one step, with many of the verified tokens rejected

尤其是当接受率不是 100% 时,每一个被拒绝的词元都意味着额外的工作被浪费。

正因如此,在高吞吐量下,vLLM 让你能够灵活配置,彻底关闭推测解码,方法是使用 --speculative-disable-by-batch-size 参数。

研究人员看到这张图后开始思考:为什么我们要在每个时间步都推测到相同的深度? 为什么不在有额外算力(批量大小较小)时进行深度推测,而在批量大小较大时进行浅层推测,甚至为每条序列动态选择推测深度:

five sequences speculating to different depths in the same step, totaling T = 13 tokens

这正是 dSpark 等想法背后的核心直觉!

来源:Hacker News · jbarrow.ai