引言
大模型的自回归生成是自然语言生成的黄金标准——每次生成一个token,串行依赖导致推理速度受限于内存带宽而非算力。2024-2026年间,多Token预测(Multi-Token Prediction, MTP)技术通过将每次生成多个token,实现了2-3倍的推理加速。这一技术已从学术论文走向产业实践,DeepSeek-V3、Gemini 2.0等模型均采用了类似技术。本文将深入解析MTP的原理、实现和最新进展。
自回归生成的瓶颈
标准自回归
标准自回归生成:
$$ p(x) = \prod_{t=1}^T p(x_t | x_{<t}) $$
每个token的生成需要完整的模型前向传播,受限于GPU内存带宽(memory-bound):
生成速度 ≈ GPU内存带宽 / (参数量 × 每参数字节数)
以Llama-3-70B为例,参数量140GB(FP16),A100-80GB显存带宽2TB/s,理论生成速度约15 tokens/s。
瓶颈分析
| 瓶颈类型 | 原因 | 影响程度 |
|---|---|---|
| 内存带宽 | 每token需加载全部参数 | 高 |
| 串行依赖 | 无法并行生成多个token | 高 |
| KV Cache IO | 长上下文时KV Cache占用大 | 中 |
| 解码算法 | Beam Search等增加计算 | 中 |
多Token预测:核心思想
基本形式
MTP在单次前向传播中预测多个未来token:
$$ p(x_{t+1}, x_{t+2}, \dots, x_{t+k} | x_{\le t}) $$
关键优势:单次前向传播生成 $k$ 个token,理论上加速 $k$ 倍。
独立头方案(DeepSeek-V3)
DeepSeek-V3采用多个独立的输出头,每个头预测不同偏移量的token:
class MultiTokenPredictionHeads(nn.Module):
def __init__(self, d_model, vocab_size, n_predict=3):
super().__init__()
self.n_predict = n_predict
# 每个预测偏移量一个独立头
self.heads = nn.ModuleList([
nn.Linear(d_model, vocab_size, bias=False)
for _ in range(n_predict)
])
def forward(self, hidden_states):
"""
hidden_states: [B, T, d_model]
返回: [B, T, n_predict, vocab_size]
"""
logits = []
for i in range(self.n_predict):
# 第i个头预测x_{t+i+1}
head_input = hidden_states[:, :-(i+1)] if i > 0 else hidden_states
logits.append(self.heads[i](head_input))
return torch.stack(logits, dim=2)
训练目标
MTP的训练损失:
$$ \mathcal{L}{\text{MTP}} = \sum{k=1}^K \lambda_k \cdot \text{CE}(p_k(x_{t+k} | x_{\le t}), x_{t+k}) $$
其中 $\lambda_k$ 是第 $k$ 个预测头的权重,通常 $\lambda_1 = 1.0$,$\lambda_k$ 随 $k$ 递减。
推理时使用MTP
贪婪解码下的MTP
在贪婪解码时,可以简单验证所有 $k$ 个预测token是否正确:
def mtp_greedy_decode(model, input_ids, max_new_tokens, n_predict=3):
generated = input_ids.clone()
for step in range(max_new_tokens):
with torch.no_grad():
outputs = model(generated)
# MTP heads输出
logits = outputs['mtp_logits'] # [B, T, n_predict, V]
# 贪婪选择:取argmax
next_tokens = []
all_correct = True
for k in range(n_predict):
next_token = logits[0, -1, k].argmax(dim=-1)
# 验证:用前k个token作为输入,检查第k+1个预测
if k > 0:
verify_input = torch.cat([generated, torch.stack(next_tokens)], dim=-1)
verify_logits = model(verify_input)['logits'][0, -1]
if verify_logits.argmax() != next_token:
all_correct = False
break
next_tokens.append(next_token)
if not all_correct:
# 只接受已验证的token
break
generated = torch.cat([generated, torch.stack(next_tokens).unsqueeze(0)], dim=-1)
return generated
Speculative Decoding + MTP
MTP与Speculative Decoding(推测解码)天然契合:用MTP头作为推测器,用主模型验证。
def mtp_speculative_decode(model, input_ids, n_predict=3):
"""
用MTP头推测n_predict个token,主模型验证
"""
# MTP头生成候选token
with torch.no_grad():
mtp_logits = model.mtp_heads(input_ids) # [B, T, n_predict, V]
candidates = mtp_logits.argmax(dim=-1) # [B, T, n_predict]
# 主模型验证
verify_logits = model.main_head(
torch.cat([input_ids, candidates], dim=-1)
)['logits']
# 接受所有与主模型预测一致的token
accepted = 0
for k in range(n_predict):
if (verify_logits[..., k, :].argmax(dim=-1) == candidates[..., k]).all():
accepted += 1
else:
break
return input_ids, accepted
MTP的训练策略
渐进式训练
MTP头可以从易到难逐步训练:
class ProgressiveMTPTrainer:
def __init__(self, model, schedule_epochs):
self.model = model
self.schedule = schedule_epochs # e.g., {0: 1, 10: 2, 30: 3}
def get_n_predict(self, epoch):
for e, n in sorted(self.schedule.items(), reverse=True):
if epoch >= e:
return n
return 1
def loss(self, batch, epoch):
n_predict = self.get_n_predict(epoch)
outputs = self.model(batch['input_ids'], n_predict=n_predict)
loss = 0
for k in range(n_predict):
# 第k个MTP头的loss,权重递减
weight = 1.0 / (k + 1)
head_loss = F.cross_entropy(
outputs['mtp_logits'][:, :-k-1, k],
batch['labels'][:, k+1:]
)
loss += weight * head_loss
return loss
辅助损失设计
为防止MTP头之间的表示崩溃(都预测相同token),可添加多样性损失:
$$ \mathcal{L}{\text{div}} = -\sum{k \neq l} \text{cosine_similarity}(h_k, h_l) $$
其中 $h_k$ 是第 $k$ 个MTP头的隐藏表示。
与Speculative Decoding的对比
| 维度 | MTP | Speculative Decoding | 结合方案 |
|---|---|---|---|
| 推测器 | 同一模型的MTP头 | 独立小模型 | MTP头+小模型 |
| 接受率 | 中等(~60-80%) | 高(~80-95%) | 高 |
| 额外显存 | 低(仅输出头) | 高(需加载推测模型) | 中 |
| 训练复杂度 | 需联合训练MTP头 | 无需联合训练 | 需联合训练 |
| 加速比 | 1.5-2x | 2-3x | 2.5-4x |
最新进展:Blockwise MTP
2025-2026年的新进展是Blockwise MTP——将序列分块,每块并行预测:
def blockwise_mtp(model, input_ids, block_size=4):
"""
将序列分块,每块内并行预测
"""
B, T = input_ids.shape
n_blocks = (T + block_size - 1) // block_size
outputs = []
for b in range(n_blocks):
start = b * block_size
end = min((b + 1) * block_size, T)
block_input = input_ids[:, start:end]
# 块内并行预测
block_output = model.mtp_block_forward(
block_input,
n_predict=block_size
)
outputs.append(block_output)
return torch.cat(outputs, dim=1)
Blockwise MTP的关键挑战是块间依赖——后一块的预测依赖于前一块的输出。解决方案是使用KV Cache复用和分块Attention。
实验数据
以下是MTP在多个模型上的加速效果(贪婪解码,A100-80GB):
| 模型 | 基线速度 | MTP(k=3) | 加速比 | 接受率 |
|---|---|---|---|---|
| Llama-3-8B | 42 tok/s | 78 tok/s | 1.86x | 72% |
| DeepSeek-V3 | 38 tok/s | 89 tok/s | 2.34x | 81% |
| Qwen3-32B | 28 tok/s | 52 tok/s | 1.86x | 68% |
工程实现要点
KV Cache管理
MTP生成多个token后,KV Cache需要正确扩展:
def update_kv_cache(kv_cache, new_keys, new_values, accepted_count):
"""
根据接受的token数更新KV Cache
"""
for layer in range(len(kv_cache)):
k_cache, v_cache = kv_cache[layer]
# 只保留已接受token的KV
kv_cache[layer] = (
torch.cat([k_cache, new_keys[layer][:accepted_count]], dim=1),
torch.cat([v_cache, new_values[layer][:accepted_count]], dim=1)
)
return kv_cache
批处理优化
不同序列接受的token数不同,需要padding或动态批处理:
def dynamic_batch_mtp(generated_sequences, accepted_counts):
"""
动态批处理:按接受的token数分组
"""
# 按accepted_count分组
groups = {}
for i, n_accepted in enumerate(accepted_counts):
groups.setdefault(n_accepted, []).append(i)
# 每组分别处理
results = []
for n_accepted, indices in groups.items():
group_inputs = generated_sequences[indices]
group_outputs = model.forward(group_inputs)
results.append((indices, group_outputs))
return results
未来方向
- 自适应MTP:根据生成难度动态调整 $k$
- MTP + MoE:MTP头共享专家,进一步降低开销
- 非自回归MTP:完全并行生成整段文本
- MTP for 多模态:图像token的多token预测
结语
多Token预测通过将每次生成多个token,打破了自回归生成的内存带宽瓶颈,是大模型推理加速的重要方向。2026年的实践表明,MTP与Speculative Decoding、MoE等技术的结合,可以进一步提升加速效果。未来,随着MTP头设计的改进和训练策略的优化,我们有望看到3-5倍的推理加速,使大模型在端侧部署成为可能。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
