MTP 完全拆解:多 token 预测如何让 DeepSeek 自带草稿模型

7678 字
38 分钟
MTP 完全拆解:多 token 预测如何让 DeepSeek 自带草稿模型

背景:解码一 token 一步,瓶颈到底在哪里#

先复习一个最基本的约束:Transformer 是自回归的,生成第 t+1t+1 个 token 之前,必须先知道第 tt 个 token。所以无论 GPU 多快,文本生成都是逐 token 串行的——这是 LLM 推理延迟的”天花板”,任何优化都绕不开它。

在这个天花板之下,每一步前向的成本主要由显存带宽决定,而不是算力。原因很简单:一个 671B 参数的模型,权重就占 671GB 显存(FP8 下约 336GB);而解码阶段每步只处理 1 个新 token,矩阵乘的算术强度极低,GPU 大部分时间都在”把权重从 HBM 搬到计算单元”,而不是真的在算。这也是本站 FlashAttention 完全拆解(一) 里讲过的 IO 瓶颈思想在解码场景的体现:解码是带宽受限(memory-bound),不是算力受限(compute-bound)。

于是自然的优化方向出现了:能不能一次前向多”赚”几个 token? 这就是投机解码(Speculative Decoding)的基本盘,经典方案(Leviathan et al., 2023Chen et al., 2023)是:

  1. 用一个小得多的草稿模型(draft model)快速自回归地猜出 γ\gamma 个候选 token;
  2. γ\gamma 个候选一次性喂给目标模型做一次并行前向验证;
  3. 接受与目标模型预测一致的前缀,第一个不一致的位置之后全部丢弃、重新生成。

只要草稿猜得准(接受率高),目标模型每步平均产出多个 token,串行步数大幅减少。本站写过的 DSpark(半自回归草稿 + 置信度调度)和 DFlash(扩散草稿)都是这个框架的变体。

但经典投机解码有一个绕不开的工程负担:你需要额外训练并部署一个草稿模型。草稿模型要与目标模型在同一个词表上、分布足够接近、还要单独维护与加载,显存也多占一份。更微妙的是,草稿模型再小也是一个完整模型,它的每一步前向也要读自己的权重——草稿阶段省下的时间,一部分又花在了草稿模型自己身上。

DeepSeek 在 2024 年 12 月发布的 DeepSeek-V3 里给出了一个很不同的答案:不另外训练草稿模型,而是在主模型的结构里”内置”一个多 token 预测模块(Multi-Token Prediction,MTP)。训练时它是给主模型提供更稠密监督信号的辅助目标,推理时它摇身一变成为草稿器——同一个模块,两种用途,这就是”自投机解码”(self-speculative decoding)的来源。DeepSeek 后续的 V3.1、V3.2 乃至 V4 系列全部沿用了这套机制,到今天它已经是 DeepSeek 推理栈里最核心的加速器之一。

这篇把它完全拆开:先讲 MTP 的思想源头(Meta 的并行多头预测),再逐公式拆解 DeepSeek-V3 的顺序 MTP 模块设计,然后推导”自投机解码”为什么能加速、能加多少,最后看它在 V3.2 与主流推理框架(vLLM、SGLang、TensorRT-LLM、llama.cpp)里的真实落地数据。

思想源头:Gloeckle 等人的并行多 token 预测#

多 token 预测本身不是 DeepSeek 发明的。2024 年 6 月,Meta AI 的 Fabian Gloeckle 等人在 Better & Faster Large Language Models via Multi-token Prediction 中首次系统性地验证了”一个位置同时预测未来多个 token”的训练目标(下文简称 Gloeckle et al., 2024)。

Gloeckle 等人的并行多 token 预测架构:在主干最后一层之上挂 D 个独立输出头,分别预测第 t+1 到 t+D 个 token
Gloeckle 等人的并行多 token 预测架构:在主干最后一层之上挂 D 个独立输出头,分别预测第 t+1 到 t+D 个 token

图:Gloeckle et al., 2024 的 Figure 1——每个位置用 D 个独立的输出头并行预测未来 D 个 token,各头之间没有信息依赖(图片来源:arXiv:2404.19737

它的机制很直接:主干(trunk)照常对第 ii 个位置的 token 计算 hidden state hi\mathbf{h}_i,然后不再只接一个输出头,而是接 D 个并行的输出头。第 kk 个头直接用同一个 hi\mathbf{h}_i 预测第 i+ki+k 个 token 的分布。所有头的预测互不依赖,可以看成把”预测下一个 token”这个任务复制了 D 份、分别对齐到未来 D 个位置。

为什么要这样做?论文的核心论证是:token 是高度可预测的,单一”下一个 token”目标给出的监督信号太稀薄。语言里大部分下一个 token 都是高频虚词(“的”、“是”、标点),对模型学习”如何计划长程结构”帮助有限;而让模型同时预测第 2、第 3、第 4 个 token,等于强制它在生成第一个 token 时就已经为后续内容做了规划。实验中,13B 参数的模型加上 4 token 预测后,在编程类任务上的表现显著提升(论文报告在 MBPP 上相对单 token 提升约 12%,而同样预算下的更大单 token 模型反而没有这个收益)。这是训练侧的事,本文不展开——记住一句话即可:多 token 预测让训练信号更稠密、模型学会”提前规划”

但 Gloeckle 的设计有一个关键局限,让它无法直接用于推理加速:D 个头是并行的,第 kk 个头预测第 i+ki+k 个 token 时,并不知道前面 k1k-1 个位置预测出了什么。可投机解码的草稿阶段恰恰要求因果链——必须先确定第 i+1i+1 个草稿 token,才能基于它预测第 i+2i+2 个。并行头的草稿就是一堆互不相干的猜测,连不成一条句子,自然无法验证。这也是为什么 Gloeckle 的论文只把多 token 预测当作训练目标,从未提过投机解码。

DeepSeek-V3 的 MTP 做的第一件事,就是把这个”并行”改成”顺序”。

DeepSeek-V3 的 MTP:顺序模块与完整因果链#

DeepSeek-V3(技术报告,2024 年 12 月)在架构章节 2.2 节里给出了自己的 MTP 设计。先看官方架构图:

DeepSeek-V3 论文 Figure 3:MTP 模块结构——共享 embedding 与输出头,第 k 个深度由投影矩阵拼接上一深度表示与第 i+k 个 token 的 embedding
DeepSeek-V3 论文 Figure 3:MTP 模块结构——共享 embedding 与输出头,第 k 个深度由投影矩阵拼接上一深度表示与第 i+k 个 token 的 embedding

图:DeepSeek-V3 论文 Figure 3——MTP 的实现:左侧是主模型主干,右侧第 k 个深度的 MTP 模块通过投影矩阵 MkM_k 组合两条输入(图片来源:DeepSeek-V3 技术报告

DeepSeek-V3 整体架构:MLA 注意力 + DeepSeekMoE 主干,最右侧串联着 MTP 多 token 预测模块
DeepSeek-V3 整体架构:MLA 注意力 + DeepSeekMoE 主干,最右侧串联着 MTP 多 token 预测模块

图:DeepSeek-V3 论文 Figure 2——模型整体架构,MTP 模块接在主干最后一层之后、输出头之前(图片来源:DeepSeek-V3 技术报告

论文用 D 个顺序的模块来预测 D 个额外的 token。第 kk 个 MTP 模块由四部分组成:

  • 一个共享的 embedding 层 Emb()\operatorname{Emb}(\cdot)(与主模型共用);
  • 一个共享的输出头 OutHead()\operatorname{OutHead}(\cdot)(与主模型共用的 unembedding 层);
  • 一个Transformer block TRMk()\operatorname{TRM}_k(\cdot)
  • 一个投影矩阵 MkRd×2dM_k \in \mathbb{R}^{d \times 2d}dd 是 hidden size)。

输入组合:两条信息拼成一条#

对于第 ii 个输入 token tit_i、第 kk 个预测深度,模块的输入由两部分拼接而成:第 ii 个 token 在k1k-1 个深度的表示 hik1Rd\mathbf{h}_i^{k-1} \in \mathbb{R}^d,以及第 i+ki+k 个 token 的 embedding Emb(ti+k)Rd\operatorname{Emb}(t_{i+k}) \in \mathbb{R}^d。两者先各自过 RMSNorm,再拼接后经线性投影:

hik=Mk[RMSNorm(hik1);RMSNorm(Emb(ti+k))],\mathbf{h}_i^{\prime k} = M_k \, [\operatorname{RMSNorm}(\mathbf{h}_i^{k-1}); \operatorname{RMSNorm}(\operatorname{Emb}(t_{i+k}))],

其中 [;][\cdot;\cdot] 表示沿特征维拼接,MkM_k2d2d 维压回 dd 维。特别地,当 k=1k=1 时,hik1\mathbf{h}_i^{k-1} 就是主模型最后一层给出的表示——第一个 MTP 模块直接吃主模型的输出。

这条公式值得逐项解释,因为每个部件都有它的”为什么”:

  • 为什么要用第 i+ki+k 个 token 的 embedding? 因为第 kk 个深度的任务是预测第 i+k+1i+k+1 个 token,而 ti+kt_{i+k} 是它前面紧挨着的那个 token——预测”下一个”之前,先让模块”看到”上一个真值 token 的信息。注意这里用的是真值 token(训练时是 ground-truth,这叫 teacher forcing):第 kk 个深度的预测链完全建立在真实历史上,而不是建立在第 k1k-1 个深度自己的猜测上。这正是论文强调的”在每个预测深度都保持完整因果链”(complete causal chain)的含义——从任何深度往前看,路径都是确定且正确的。
  • 为什么拼接两路而不是只给 embedding? 预测 ti+k+1t_{i+k+1} 只靠 ti+kt_{i+k} 的 embedding 是不够的——那就退化成 bigram 语言模型了。hik1\mathbf{h}_i^{k-1} 携带了模型对第 ii 个位置全部上下文的理解(这个表示在主模型的第 k1k-1 层深度上已经过完整推理),拼接后模块同时拥有”当前位置的深层语义”和”紧邻的未来 token 信息”,两者结合才能做出高质量预测。注意位置关系:hi\mathbf{h}_i 属于位置 ii,而 Emb(ti+k)\operatorname{Emb}(t_{i+k}) 属于位置 i+ki+k,两者相差 kk 个位置——这 kk 步的跨度正是用 MkM_k 这条”捷径”补上的。
  • 为什么要 RMSNorm? 两条输入来自不同空间(一个是深层表示,一个是浅层 embedding),量纲和分布差异很大。RMSNorm 先把两者各自归一化到相同尺度,再拼接,避免投影矩阵被某一侧的数值主导。这也是 DeepSeek 全系架构的标准做法(MLA、DeepSeekMoE 都用 RMSNorm)。
  • 为什么 MkM_k 的形状是 d×2dd \times 2d 输入拼接后是 2d2d 维,输出要恢复成 Transformer block 期望的 dd 维输入,所以投影矩阵必须是 d×2dd \times 2d。这是这个模块唯一”新增”的参数(与 Gloeckle 的独立输出头不同,MkM_k 很小,参数量为 2d22d^2,对 671B 模型可以忽略不计)。

经过 Transformer block 与共享输出头#

组合后的 hik\mathbf{h}_i^{\prime k} 送入第 kk 个深度的 Transformer block,得到该深度的输出表示:

h1:Tkk=TRMk(h1:Tkk),\mathbf{h}_{1:T-k}^{k} = \operatorname{TRM}_k(\mathbf{h}_{1:T-k}^{\prime k}),

其中 TT 是输入序列长度,i:ji:j 表示切片操作(左右边界都包含)。序列长度从 TT 减到 TkT-k,是因为第 i+ki+k 个 token 的 embedding 最多取到 tTt_{T},所以 ii 最大只能到 TkT-k——序列末尾的 kk 个位置没有足够的”未来 token”可用。

最后,把 hik\mathbf{h}_i^{k} 交给共享输出头,得到第 kk 个额外预测 token 的概率分布 Pi+k+1kRVP_{i+k+1}^{k} \in \mathbb{R}^{V}VV 是词表大小):

Pi+k+1k=OutHead(hik).P_{i+k+1}^{k} = \operatorname{OutHead}(\mathbf{h}_i^{k}).

输出头就是主模型的 unembedding 层:线性映射到 logits 后接 softmax。注意索引:第 kk 个模块用位置 ii 的表示预测位置 i+k+1i+k+1 的 token,偏移恰好是 k+1k+1。整个结构串起来就是:主干 → 投影 + 拼接 → 一层 Transformer → 共享输出头 → 第 k+1k+1 个未来 token 的分布

设计决策:为什么是”顺序模块”而不是”并行头”#

把 DeepSeek-V3 的 MTP 与 Gloeckle 的并行多头、EAGLE 的基于特征的草稿放在一起对比,能看清 DeepSeek 每一步选择的理由:

方案额外结构预测方式推理时能否当草稿代表工作
并行多头预测D 个独立输出头各头独立预测,无因果链不能Gloeckle et al., 2024
独立草稿模型完整的小模型独立自回归能,但需额外训练/部署Leviathan et al., 2023;Chen et al., 2023
特征级草稿轻量解码器吃主干 hidden state顺序、有条件依赖能,接受率高EAGLE / EAGLE-2 / EAGLE-3
DeepSeek MTP顺序 Transformer block + 共享头顺序、完整因果链能(V3.2 起官方支持)DeepSeek-V3

关键区别在两点:

  1. 顺序性。第 kk 个模块的输入包含第 i+ki+k 个 token 的信息,而第 i+ki+k 个 token 正是前 kk 个模块”负责”的位置——这保证了每个深度的预测都建立在确定的前缀上。推理时若把 MTP 模块当草稿器,草稿 token 也是按这个因果链逐个产生的,这正是投机解码的要求。
  2. 共享 embedding 与输出头。论文里明确说每个模块的 embedding 层和输出头都与主模型共享。embedding 共享意味着 MTP 模块直接消费主模型的输入表示空间;输出头共享意味着它的预测落在与主模型完全相同的输出分布空间。这样设计一是省参数(D 个模块只多出 D 个 Transformer block 和 D 个投影矩阵),二是让 MTP 的预测分布天然靠近主模型——后者对推理时的接受率至关重要,后面会看到。

参数开销具体有多少?DeepSeek-V3 发布版配置了 D=1,即 1 个 MTP 模块(对应模型配置文件里的 num_nextn_predict_layers: 1)。模块主体是一个与主模型同构的 Transformer block(约一层 MoE 的体量),加上投影矩阵,总共约 14B 参数,相对 671B 主模型只增加约 2%——这是 V3-0324 检查点 685B 总参数与 V3 671B 之差的来源(Hugging Face 讨论NVIDIA Megatron-LM 文档)。相比之下,一个独立的草稿模型动辄几十亿参数且分布与主模型有 gap,MTP 用 2% 的参数代价换来了一个”分布几乎一致”的草稿器。

MTP 训练目标:给主模型加一份稠密监督#

训练时,每个深度各自算一个交叉熵损失。第 kk 个深度的损失是:

LMTPk=CrossEntropy(P2+k:T+1k,t2+k:T+1)=1Ti=2+kT+1logPik[ti],\mathcal{L}_{\text{MTP}}^{k} = \operatorname{CrossEntropy}\left(P_{2+k:T+1}^{k}, \, t_{2+k:T+1}\right) = -\frac{1}{T}\sum_{i=2+k}^{T+1}\log P_{i}^{k}[t_{i}],

其中 tit_i 是第 ii 个位置的真值 token,Pik[ti]P_i^{k}[t_i] 是第 kk 个 MTP 模块给出的、tit_i 被预测到的概率。这本质上是把”预测第 i+k+1i+k+1 个 token”的交叉熵在序列上取平均——注意下标从 2+k2+k 开始,与前面序列切片的原因一致(前 k+1k+1 个位置没有足够未来上下文)。

总损失是各深度损失的均值再乘一个权重系数 λ\lambda

LMTP=λDk=1DLMTPk,\mathcal{L}_{\text{MTP}} = \frac{\lambda}{D}\sum_{k=1}^{D}\mathcal{L}_{\text{MTP}}^{k},

DeepSeek-V3 中 λ\lambda0.1Megatron-LM 的 MTP 实现文档确认了这一取值)。λ\lambda 调得小的原因很实际:MTP 只是辅助目标,不能喧宾夺主地干扰主模型的 next-token 学习。训练效果上,论文报告 MTP 让模型在标准基准上普遍受益(尤其在数学与代码任务上),代价是约 3% 的训练时间增加——训练侧的效果本文点到为止,不再展开。

论文原话:推理时两用#

论文在 “MTP in Inference” 一段里写得很直白:

我们的 MTP 策略主要目的是提升主模型的性能,因此推理时可以直接丢弃 MTP 模块,主模型照常独立工作。此外,我们也可以把这些 MTP 模块重新用于投机解码,进一步改善生成延迟。

这句话点明了 MTP 的双重身份:训练时它是给主模型”加课”的辅助目标,推理时它是不需要额外训练就存在的草稿模型。V3 发布时 DeepSeek 没有公开 MTP 权重(投机解码只停留在官方内部),到 V3.2-Exp 才把这条推理路径正式开放并推广。下面推导它到底怎么加速、能加速多少。

自投机解码:MTP 模块如何当草稿模型#

草稿-验证-接受的三段式流程#

自投机解码与经典投机解码的流程骨架完全一样,区别只在草稿从哪来:

  1. 草稿阶段(draft):主模型输出第 tt 个 token 后,把它的最后一层 hidden state ht\mathbf{h}_t 送入第 1 个 MTP 模块,结合刚生成 token 的 embedding,预测出草稿 token t^t+1\hat{t}_{t+1};然后把这个草稿 token 的 embedding 传给第 2 个深度(或同一模块的下一轮),预测 t^t+2\hat{t}_{t+2}……如此自回归地跑 γ\gamma 步。注意此时 MTP 模块里”下一 token 的 embedding”不再是真值,而是上一轮自己预测出来的草稿 token——训练时的 teacher forcing 在推理时换成了自回归,因果链仍然保持。
  2. 验证阶段(verify):把 γ\gamma 个草稿 token 拼在当前序列后面,主模型做一次完整的并行前向,得到每个位置的真实预测分布。这次前向同时算出了 γ+1\gamma+1 个位置的结果(包括真正的第 t+1t+1 个 token),成本与普通解码一步相同。
  3. 接受阶段(accept):从第 t+1t+1 个位置开始,逐个比较草稿与主模型预测:一致就接受(贪婪模式下直接接受,采样模式下按拒绝采样规则接受),直到第一个不一致的位置为止,其后的草稿全部丢弃,下一轮从这个”分歧点”重新开始草稿。

因为验证一步并行覆盖了 γ+1\gamma+1 个位置,而主模型每步只算一次前向,所以平均每个主模型前向产出的 token 数从 1 变成了 >1>1,解码速度随之提升。

加速比的推导:接受率与草稿成本#

设草稿长度 γ\gamma、每个草稿位置被接受的概率(接受率)为 α\alpha,主模型一次前向的成本记为 1,草稿阶段每个 token 的成本记为 β\betaβ1\beta \ll 1,原因见下)。

期望产出 token 数:一轮中至少接受 1 个的概率是 1,至少接受 2 个的概率是 α\alpha,至少接受 3 个是 α2\alpha^2……至少接受 γ+1\gamma+1 个是 αγ\alpha^{\gamma}γ\gamma 个草稿全部通过,额外还赚到第 γ+1\gamma+1 个验证位置)。期望产出:

E=1+α+α2++αγ=1αγ+11α.E = 1 + \alpha + \alpha^2 + \cdots + \alpha^{\gamma} = \frac{1 - \alpha^{\gamma+1}}{1 - \alpha}.

期望成本γ\gamma 步草稿 + 1 次验证,即 γβ+1\gamma \beta + 1

加速比

S=E1+γβ=1αγ+1(1α)(1+γβ).S = \frac{E}{1 + \gamma\beta} = \frac{1 - \alpha^{\gamma+1}}{(1 - \alpha)(1 + \gamma\beta)}.

这个公式是理解一切投机解码(包括 MTP)的钥匙,值得记下来。两个极端情况验证一下:α=0\alpha=0(草稿全错)时 S=1/(1+γβ)<1S = 1/(1+\gamma\beta) < 1,白白多花了草稿成本;α1\alpha \to 1S(γ+1)/(1+γβ)γ+1S \to (\gamma+1)/(1+\gamma\beta) \approx \gamma+1,主模型每步白赚 γ+1\gamma+1 个 token。

MTP 的成本优势:为什么 β\beta 小、α\alpha#

现在把 MTP 的自投机场景代入这两个量:

草稿成本 β\beta:草稿阶段每步只跑 MTP 模块——一个 Transformer block + 共享输出头。主模型有 61 层,而 MTP 模块是主干之外的一个额外 block(V3 配置下只有 1 个模块,D=1),所以单步草稿的计算量约为主模型完整前向的 1/611.6%1/61 \approx 1.6\%,加上输出头投影,β0.02\beta \approx 0.02。相比之下,经典投机解码的草稿模型即使小一个数量级(如 1.5B 对 13B),β\beta 也在 0.1 左右;对 MoE 大模型,独立草稿模型与主模型之间的参数量差距往往更小,β\beta 很难压下来。MTP 把 β\beta 压到了接近极限——草稿器与验证器共享了几乎全部权重。

接受率 α\alpha:草稿质量决定接受率。MTP 的草稿来自主模型自己的表示空间:第 1 个 MTP 模块直接吃主模型最后一层 hidden state,而主模型的最后一层表示恰恰是最接近”正确下一个 token 分布”的特征(EAGLE 系列工作的核心洞察也是这个:用主模型的隐藏状态预测草稿,接受率远高于独立小模型)。V3 的 MTP-1(γ=1\gamma=1)在部署中实测接受率约 85%–90%AI Wiki 对多 token 预测的整理xLLM 文档 同样引用这一数据)。

代入公式看 V3 的 MTP-1:α=0.87,γ=1,β=0.02\alpha = 0.87, \gamma = 1, \beta = 0.02

S=10.872(10.87)(1+0.02)=0.24310.13×1.021.83.S = \frac{1 - 0.87^2}{(1 - 0.87)(1 + 0.02)} = \frac{0.2431}{0.13 \times 1.02} \approx 1.83.

与多个独立来源报告的”DeepSeek-V3 上 MTP 带来约 1.8 倍生成吞吐加速”(AI WikixLLM 文档SegmentFault 解读)严丝合缝。模型预测得越准(α\alpha 越高),收益越大——α=0.9\alpha=0.9 时 MTP-1 加速约 1.9 倍,α=0.95\alpha=0.95 时约 1.95 倍。

为什么 V3 生产环境只用 MTP-1(γ=1\gamma=1)而不是更长的草稿? 公式揭示了一个微妙权衡:γ\gamma 越大,每轮期望产出 EE 越高(SS 的分子变大),但 (1) 草稿成本 γβ\gamma\beta 线性上升,(2) 更关键的是,第 kk 个草稿位置的接受率会随 kk 衰减——预测距离越远越难。MTP-1 只预测紧邻的下一个 token,接受率 85–90%;如果强推 MTP-3,第三个位置的接受率会显著下降,且高并发下验证阶段的 batch 增大、内存带宽压力上升,总吞吐可能不升反降。这也是为什么 TensorRT-LLM 的 DeepSeek-V3.2 优化博客 建议延迟敏感场景用 MTP-3、其余场景 MTP-1 通常已够用——低延迟(batch 小)时草稿成本占比低、收益显著;高吞吐(batch 大)时草稿与验证的带宽竞争加剧,MTP-1 更稳。

生产落地:V3.2 自投机解码与框架生态#

DeepSeek-V3.2-Exp:官方正式开放自投机解码#

2025 年 9 月 29 日发布的 DeepSeek-V3.2-Exp(官方技术文档,与 DeepSeek-V3.2-Exp 模型卡)有两件大事:一是把 DeepSeek Sparse Attention(DSA,稀疏注意力,本站 NSA 系列 已拆解过它的 kernel 与工程落地)做成了正式特性;二是把 MTP 自投机解码作为官方推荐的推理加速路径开放出来——MTP 模块的权重随模型发布,vLLM、SGLang 等框架用 method: "deepseek_mtp" 即可开启。官方同时将长上下文推理成本大幅下调(公开报道称 API 成本下降超过 50%),其中自投机解码与 DSA 各贡献了一部分。

DeepSeek-V3.2-Exp 的注意力架构:DSA 稀疏注意力实例化在 MLA 之上,lightning indexer 为每个 query 选出 top-k 的 KV 条目
DeepSeek-V3.2-Exp 的注意力架构:DSA 稀疏注意力实例化在 MLA 之上,lightning indexer 为每个 query 选出 top-k 的 KV 条目

图:DeepSeek-V3.2-Exp 论文 Figure 1——DSA 实例化在 MLA 之上,绿色部分展示了 indexer 如何为 query 选出 top-k 键值条目(图片来源:DeepSeek-V3.2-Exp 官方文档

V3.2 里 MTP 与 DSA 的配合方式值得一提:MTP 草稿阶段会产生 γ\gamma 个额外的 query token,这些草稿 token 在验证时是作为同一个 query 组(query group)一次性进入注意力计算的——DSA 的 indexer 可以为整个 query 组共享一次 top-k 选择,草稿 token 无需重新计算选择结果。后续的 PIVOT 论文(query 组索引的 token 级稀疏注意力)直接确认:生产环境中的 DeepSeek-V3.2 正是以 MTP 深度 3(d=3,即 4 个 query 一组) 部署的,稀疏注意力与自投机解码是”买一送一”的关系——草稿 token 天然构成 query 组,几乎零额外成本。

框架适配:一个 kernel 层面的硬约束#

MTP 从论文到生产,真正的工程难点不在算法而在 kernel。V3.2 的 DSA 解码依赖一个 MQA(Multi-Query Attention)风格的 indexer kernel,而这个 kernel 最初只支持序列长度 1 或 2——也就是只能处理 MTP-off 或 MTP-1。要让 MTP-3 跑起来,TensorRT-LLM 的解决方案(PR-9045) 是把序列维展平(flatten)到 batch 维:把 4 个 query token 当成 4 个 batch 项喂给 kernel,序列长度恒为 1。这个 trick 有个副作用:flatten 后 kernel 会忽略因果掩码(对角线区域的遮盖),但随后 top-k 选择阶段会重新正确地施加因果掩码,所以最终选出的 top-k 索引不受影响。vLLM 的 PR #36982 走了另一条路:当 MTP=1 时直接利用 indexer 的原生支持,不再 flatten。而 DeepSeek 自己的 DeepGEMM 库则在 commit 2be3f36 中给稀疏 MLA kernel 加上了原生 MTP-3 支持——从”绕过限制”到”消除限制”,这是生态走向成熟的过程。

实测数据:各框架的 MTP 加速#

  • SGLang(NextN,PR #3582:首个在 SGLang 中支持 DeepSeek-V3/R1 NextN(即 MTP)投机解码的 PR,把 nextn 层导出为草稿模型单独加载。实测 R1 在 2 节点 8×H20 上:batch=1 时吞吐从 17 提升到 52 token/s(约 3 倍),batch=30 时从 160 提升到 500 token/s(约 3.1 倍)。
  • 百度百舸 × SGLang(开源生产级 MTP 代码:2025 年 10 月开源了为 V3.2 DSA 架构深度定制的 MTP 推理实现(SGLang PR #11652),因为 DSA 改变了 KV 管理方式,旧版 MTP 代码无法直接复用。实测 V3.2 解码吞吐提升超过 2 倍,并且经过了大规模生产环境验证(InfoQ 报道)。
  • TensorRT-LLM(Blackwell 优化博客:在 B200/GB200 上验证 MTP-1/MTP-3 的配置组合,配合 FP8 稀疏 MLA 优化,报告了最高约 47% 的吞吐提升;再次印证”延迟敏感用 MTP-3,其他场景 MTP-1”的经验法则。
  • xLLM(MTP 文档:支持把 DeepSeek-V3/V3.2/R1 的 MTP 层导出为 sidecar 草稿权重。实测(ShareGPT 输入 2500 / 输出 1500 token):并发 1 时平均 TPOT 从 40.61ms 降到 28.33ms(约 -30%),输出吞吐从 24.20 提升到 35.19 token/s;并发 4 时输出吞吐从 79.83 提升到 111.18 token/s。
  • llama.cpp(PR #22673:2026 年 5 月合入 MTP 支持,RTX 3090 上跑 Qwen3.6 27B 实测从 38 提到 65 token/s(约 1.7 倍)。这件事的意义不在数字本身,而在于 MTP 从”671B 数据中心的专属特权”变成了消费级单卡也能用的通用机制——任何训练过 MTP 头的模型都能直接受益。

局限与边界#

把 MTP 自投机解码放进真实服务,有三个必须知道的边界:

  1. 高并发下收益缩水甚至为负。SGLang PR #3582 的评论区有一个真实案例:2 节点 8×H800 上跑 V3,高负载时 MTP 投机解码反而慢于普通解码(18.91 vs 30.02 token/s)。原因前面推导过:草稿成本 γβ\gamma\beta 在高并发时不再是”免费”的——草稿 token 与验证 token 争抢同一批 GPU 的算力和带宽,batch 越大,验证阶段本身已经接近带宽饱和,多跑的草稿就是纯开销。投机解码类方法本质上是”用计算换串行步数”,在带宽受限的稠密场景下这笔交易尤其划算,在算力饱和的场景下就要打问号。
  2. 草稿长度是静态的,接受率是动态的。MTP-1/3 的 γ\gamma 在部署时写死,但实际接受率随 prompt 难度、生成阶段剧烈波动——简单续写时 α\alpha 接近 0.95,长程推理时可能掉到 0.6 以下。静态 γ\gamma 要么保守(MTP-1,错过高接受率时的收益),要么激进(MTP-3,接受率低时白跑)。本站写过的 DSpark(置信度调度验证)正是冲着这个缺陷去的:它用外部半自回归草稿模型 + 逐 token 置信度调度,在 V4 上相对 MTP-1 基线再拿 60–85% 的每用户生成加速——这也侧面说明 MTP-1 是 2026 年 DeepSeek 生产栈的事实基线。
  3. 显存与权重管理成本。MTP 模块虽然只占 2% 参数量,但 14B 权重依然要常驻显存(或至少与主模型同机加载)。对显存捉襟见肘的部署(比如单卡跑 27B 的 llama.cpp 场景),开 MTP 意味着要预留额外空间,用户需要在”更快”与”更省”之间做选择。

设计哲学:为什么这是 DeepSeek 风格的最优解#

把整个机制再回望一遍,MTP 的设计有三个层层递进的选择,每一个都”顺便”解决了下一个问题:

  1. 训练侧要多 token 监督(Gloeckle 已验证)→ 但并行头没有因果链 → 改成顺序模块,共享 embedding 与输出头。
  2. 顺序模块天然具备自回归能力 → 推理时它就是一个现成的草稿器 → 且因为草稿器与验证器共享表示空间,接受率远高于独立小模型 → 这就是”自投机解码”。
  3. 接受率再高也受草稿长度与负载制约 → 生产环境用 MTP-1 打底,按场景上调到 MTP-3,或叠加外部调度(DSpark)→ 与稀疏注意力(DSA)天然互补,草稿 token 就是现成的 query 组。

一条线贯穿始终:不让任何机制只为一个目的服务。MTP 训练时是监督信号,推理时是草稿模型;MLA 训练时省激活,推理时省 KV 缓存;DSA 训练时省算力,推理时省带宽。DeepSeek 的架构设计几乎从不引入”只对推理有用”或”只对训练有用”的孤立组件——每个组件都同时优化训练与推理两个阶段。这正是它能把每 token 推理成本一路打下来的底层原因。

小结#

  • MTP(Multi-Token Prediction)是 DeepSeek-V3 引入的多 token 预测机制:D 个顺序的 MTP 模块接在主干之后,第 kk 个模块把上一深度的表示与第 i+ki+k 个真值 token 的 embedding 拼接投影后,经过一层 Transformer block 预测第 i+k+1i+k+1 个 token,所有模块共享主模型的 embedding 与输出头,新增参数约 14B(占 2%)。
  • 训练时它是给主模型加稠密监督的辅助目标(LMTP=λDkLMTPk\mathcal{L}_{\text{MTP}} = \frac{\lambda}{D}\sum_k \mathcal{L}_{\text{MTP}}^kλ=0.1\lambda=0.1);推理时论文明确说可以”重新用于投机解码”。
  • 自投机解码把 MTP 模块当草稿器、主模型当验证器,加速比 S=1αγ+1(1α)(1+γβ)S = \frac{1-\alpha^{\gamma+1}}{(1-\alpha)(1+\gamma\beta)}。MTP 的 β0.02\beta\approx0.02(草稿器只有一层)、α\alpha 达 85–90%,代入得 V3 的 MTP-1 约 1.8 倍加速,与实测吻合。
  • V3.2-Exp 正式开放自投机解码,与 DSA 稀疏注意力天然互补(草稿 token 构成 query 组);vLLM、SGLang、TensorRT-LLM、xLLM、llama.cpp 均已落地,报告 1.7–3 倍不等的加速;高并发下收益会缩水甚至为负,草稿长度与负载的匹配是工程上的核心权衡。

如果顺着这条线继续往下挖,最值得展开的对比是:MTP 这类”训练时内置、部署时静态草稿长度”的方案,与 DSpark 这类”独立草稿模型 + 动态置信度调度”的方案,在真实负载下的收益边界分别在哪里——这会是下一篇很好的题材。

参考资料#

  1. DeepSeek-V3 Technical Report(arXiv:2412.19437,MTP 设计、公式与实验的原始出处)
  2. Better & Faster Large Language Models via Multi-token Prediction(Gloeckle et al., 2024,arXiv:2404.19737)
  3. DeepSeek-V3.2-Exp 官方技术文档(GitHub 仓库中的 DeepSeek_V3_2.pdf,DSA 与自投机解码背景)
  4. DeepSeek-V3.2-Exp 模型卡(Hugging Face,官方发布说明)
  5. Optimizing DeepSeek-V3.2 on NVIDIA Blackwell GPUs(TensorRT-LLM 技术博客,MTP-1/MTP-3 配置建议与 kernel 限制)
  6. Support NextN (MTP) speculative decoding for DeepSeek-V3/R1(SGLang PR #3582,含实测吞吐数据)
  7. 百度百舸 × SGLang:开源生产级 MTP 代码,助力 DeepSeek-V3.2 推理服务 2 倍以上吞吐提升
  8. xLLM 的 MTP 推理文档(含 V3 接受率与 TPOT 实测数据)
  9. Multi-token prediction(AI Wiki 词条,含自投机解码 3 倍吞吐与 V3 约 1.8 倍数据)
  10. NVIDIA Megatron-LM 的 MTP 实现文档(λ=0.1 与实现细节出处)
  11. llama.cpp PR #22673:MTP 支持(消费级 GPU 上 27B 模型约 1.7 倍加速)
  12. PIVOT: Efficient Query-Group Indexing for Token-Level Sparse Attention(确认 V3.2 生产环境 MTP 深度 3 的部署形态)
  13. Fast Inference from Transformers via Speculative Decoding(Leviathan et al., 2023,投机解码原始论文)
  14. Accelerating Large Language Model Decoding with Speculative Sampling(Chen et al., 2023)

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

MTP 完全拆解:多 token 预测如何让 DeepSeek 自带草稿模型
https://pinghaoyang.com.cn/aigc/posts/deepseek-mtp/
作者
平昊阳
发布于
2026-08-29
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
平昊阳
乘长风,破巨浪, 展鸿图于未央!
--
总访问量
--
访客数
公告
欢迎来到我的个人博客!欢迎关注交流吖!
更多相关公告,见
社交-留言」。
音乐
封面

音乐

暂未播放

0:000:00
暂无歌词
站点统计
文章
88
分类
18
标签
114
总字数
747,863
运行时长
0
最后活动
0 天前

文章目录