☰
大模型推理加速实战:量化、投机采样与PD分离的落地指南
2026/10/1 18:06:58 网站建设 项目流程

大模型推理这件事,真正落到生产环境里,最扎心的往往不是模型效果,而是延迟和成本。一个 70B 级别的模型,如果老老实实用 FP16 跑,单张 80G 显存卡连权重都放不下,更别提 KV Cache 和并发请求了。我最早接触这块的时候,天真地以为"推理加速"就是换个更快的 GPU,后来才发现,真正的加速发生在算法和系统层面——量化把权重压小,投机采样把串行解码变成并行验证,PD 分离把预填充和解码这两件性质完全不同的事拆到不同硬件上跑。这三样东西,基本构成了当前大模型推理加速的三根支柱。

这篇内容我想把这三项技术从"是什么"讲到"怎么落地",重点不是复述论文,而是把我在实际部署中踩过的坑、算过的账、调过的参数摊开来讲。适合已经跑通过基础推理服务、想进一步压延迟降成本的工程师,也适合刚接触推理优化、想建立整体认知的同学。读完之后,你应该能判断自己的场景该先上哪一项、每项技术的收益边界在哪、以及哪些参数是真正影响性能的关键。

1. 为什么推理加速绕不开这三条路

1.1 推理的两个阶段,决定了优化的两个方向

要理解加速技术,得先搞清楚大模型推理到底在干什么。一次完整的生成请求,其实分成两个性质截然不同的阶段:Prefill(预填充)和Decode(解码)。

Prefill 阶段处理的是你输入的整段 prompt,所有 token 一次性送进模型,做的是大规模的矩阵乘法。这个阶段的特点是计算密集,GPU 的算力能被吃得很满,属于"算力瓶颈"。而 Decode 阶段是逐 token 生成的,每生成一个 token 都要把整个模型权重读一遍,但实际参与计算的数据量很小,属于访存密集,GPU 的算力利用率往往只有个位数百分比,瓶颈在显存带宽。

这个区别极其关键。因为量化主要优化的是"权重占多大、读多快",直接打在 Decode 的访存瓶颈上;投机采样优化的是"一次前向能出几个 token",减少 Decode 的循环次数;PD 分离则是承认这两个阶段硬件需求不同,干脆拆开部署。三条路,对应三个不同的瓶颈点,这也是为什么它们能叠加使用而不是互相替代。

1.2 一个反直觉的账:为什么 Decode 阶段 GPU 在"摸鱼"

我拿一个具体的例子算给你看。假设跑一个 13B 模型,FP16 权重约 26GB。Decode 阶段生成一个 token,需要把 26GB 权重从显存完整读一遍。一张 A100 的显存带宽大约是 2TB/s,那么读一遍权重的时间是 26GB / 2000GB/s ≈ 13ms。而这张卡的 FP16 算力是 312 TFLOPS,生成一个 token 的计算量大约是 2 × 13B = 26 GFLOP,算下来计算时间只有 26e9 / 312e12 ≈ 0.08ms。

也就是说,访存时间是计算时间的 160 多倍。GPU 的算力单元绝大部分时间在等数据从显存搬过来。这就是 Decode 阶段的真相——不是算不动,是喂不饱。理解了这一点,你就明白为什么量化(减少要读的数据量)和投机采样(一次多出几个 token,摊薄权重读取成本)能带来那么大的收益了。

1.3 三项技术的收益量级与适用边界

在动手之前,先建立一个收益预期,免得期望落空。根据我的实测经验,这三项技术的典型收益大致如下:

技术主要优化目标典型收益主要代价
量化(INT8/INT4)显存占用、访存带宽显存降 50%-75%,吞吐提升 1.5-3x精度损失、部分算子需适配
投机采样Decode 循环次数延迟降 1.5-3x(取决于接受率)额外草稿模型开销、实现复杂
PD 分离资源利用率、TTFTTTFT 降 30%-60%,吞吐提升明显部署复杂度、KV 传输开销

需要强调的是,这些收益不是简单相乘的。量化和投机采样叠加时,草稿模型的接受率可能因为量化而下降;PD 分离的收益高度依赖你的请求特征(prompt 长度、并发量)。所以别指望"三个都上就快 10 倍",实际落地要一项一项测。

2. 量化:把权重压小,让访存不再拖后腿

2.1 量化的本质是一次"精度换带宽"的交易

量化的核心思想很朴素:神经网络权重里那些 FP16 的数字,其实不需要那么高的精度。一个 FP16 数占 2 字节,如果我用 INT8 表示,就只占 1 字节,显存直接减半,访存带宽需求也减半。极端一点用 INT4,只占 0.5 字节,理论上能压到原来的四分之一。

但这里有个关键问题:权重的数值范围差异很大,有的层数值集中在 [-0.1, 0.1],有的层能到 [-5, 5]。如果统一用一个缩放因子把 FP16 映射到 INT8 的 [-127, 127],那些数值范围小的层就会被"压扁",精度损失严重。所以量化的核心难点从来不是"怎么压",而是"怎么压得准"。

2.2 从 PTQ 到 QAT:两条技术路线的取舍

按量化发生的时机,主流方案分两类:

PTQ(训练后量化)是拿一个训练好的模型,用一批校准数据跑一遍,统计各层的数值分布,然后确定缩放因子。优点是快,几十分钟就能搞定,不需要重新训练。缺点是精度损失相对大,尤其是低比特(INT4)时。GPTQ、AWQ 都属于这一类。

QAT(量化感知训练)是在训练过程中就模拟量化的舍入误差,让模型"提前适应"低精度。精度保持得更好,但需要完整的训练流程和算力,成本高得多。一般只有在对精度极其敏感、且 PTQ 实在救不回来的场景才用。

对绝大多数推理部署场景,我的建议是先上 PTQ。GPTQ 和 AWQ 在 4bit 下的精度损失通常可以控制在 1% 以内(用困惑度衡量),对实际业务几乎无感。除非你的任务对数值极其敏感(比如某些科学计算),否则没必要碰 QAT。

2.3 权重量化、激活量化与 KV Cache 量化

很多人一说量化就只想到权重,其实量化有三个可以下手的地方,收益和难度各不相同:

  • 权重量化:最成熟,收益最直接。权重是静态的,可以离线量化好,推理时直接加载。INT8/INT4 权重是标配。
  • 激活量化:激活值是动态的,每次输入不同,范围会变。要做在线量化,需要动态统计,实现复杂,精度也更难保证。W8A8(权重 8bit、激活 8bit)是常见组合。
  • KV Cache 量化:这个容易被忽略,但在长上下文场景下收益巨大。KV Cache 会随着序列长度线性增长,一个 32K 上下文的请求,KV Cache 可能比权重还占显存。把 KV Cache 量化到 INT8,显存能省一半,而且对精度影响通常很小。

我的经验是:权重先量化到 INT4,KV Cache 量化到 INT8,激活量化看情况。这个组合在显存和精度之间平衡得最好。

2.4 实操:用 GPTQ 量化一个模型并验证精度

下面给一个可复现的流程。假设你有一个 FP16 的模型,想量化成 4bit。

# 依赖:auto-gptq, transformers, datasets from auto_gptq import AutoGPTQForCausalLM, BaseQuantizeConfig from transformers import AutoTokenizer from datasets import load_dataset model_id = "your-model-path" tokenizer = AutoTokenizer.from_pretrained(model_id) # 量化配置:4bit,group_size=128 是精度和压缩率的平衡点 quantize_config = BaseQuantizeConfig( bits=4, group_size=128, desc_act=False, # 关闭激活重排序,速度更快,精度略降 ) # 准备校准数据,128-256 条即可,覆盖你的业务分布 calib_dataset = load_dataset("your-calib-data", split="train[:256]") calib_texts = [tokenizer(t) for t in calib_dataset["text"]] model = AutoGPTQForCausalLM.from_pretrained(model_id, quantize_config) model.quantize(calib_texts) model.save_quantized("your-model-4bit")

量化完之后,一定要做精度验证,别直接上线。验证方法是用同一批测试数据,分别跑 FP16 和量化模型,对比困惑度(PPL)和实际任务指标。

# 简单的 PPL 对比 import torch from transformers import AutoModelForCausalLM def compute_ppl(model, tokenizer, texts): model.eval() total_loss, total_tokens = 0, 0 with torch.no_grad(): for text in texts: inputs = tokenizer(text, return_tensors="pt").to(model.device) outputs = model(**inputs, labels=inputs["input_ids"]) total_loss += outputs.loss.item() * inputs["input_ids"].size(1) total_tokens += inputs["input_ids"].size(1) return torch.exp(torch.tensor(total_loss / total_tokens))

注意:group_size 是个关键参数。设成 128 时,每 128 个权重共享一个缩放因子,精度和压缩率平衡较好;设成 -1 表示整层共享一个缩放因子,压缩率最高但精度损失大。我实测下来,128 是大多数场景的甜点。

2.5 量化踩坑实录:那些文档不会告诉你的问题

坑一:不是所有算子都支持量化。有些模型用了特殊的算子(比如某些自定义的 LayerNorm 变体),量化工具链可能不支持,会直接报错或者静默回退到 FP16,导致你以为量化了其实没有。部署前一定要检查实际加载后的显存占用。

坑二:量化后的模型在长文本上精度衰减更明显。短文本测试 PPL 只涨了 0.1,看着很美,但一到长上下文,误差会累积放大。我的做法是专门用长文本测试集验证,别只测短句。

坑三:不同推理框架对量化格式的支持不一样。GPTQ 格式在 vLLM 里支持很好,但换成别的框架可能就要转格式。选量化方案前,先确认你的推理框架支持哪种格式,别量化完了发现跑不起来。

3. 投机采样:用"草稿+验证"打破串行魔咒

3.1 自回归解码的串行困境

Decode 阶段最要命的地方在于它是严格串行的:生成第 N 个 token 必须等第 N-1 个 token 算完。这意味着你没法通过并行来加速,只能一个接一个地出。前面算过,每出一个 token 要读一遍全部权重,13ms 就为了出一个字,这效率实在感人。

投机采样的思路很巧妙:既然大模型一次前向只能出一个 token 太浪费,那我能不能一次前向验证多个 token?具体做法是,先用一个又小又快的"草稿模型"一口气生成 K 个候选 token,然后把这 K 个 token 一起送给大模型,让大模型一次性验证这 K 个 token 哪些是对的。因为大模型的一次前向本来就要读一遍权重,验证 1 个 token 和验证 K 个 token 的访存成本几乎一样,所以如果 K 个里有多个被接受,就相当于"白赚"了。

3.2 接受率才是决定收益的唯一指标

投机采样的收益公式其实很简单:

加速比 ≈ 平均接受 token 数 / (1 + 草稿模型开销占比)

假设草稿模型的开销是大模型的 1/5,平均每次接受 3 个 token,那么加速比大约是 3 / 1.2 ≈ 2.5x。但如果接受率很低,平均只接受 1 个 token,那加速比就接近 1,甚至因为草稿模型的开销而变慢。

所以接受率是投机采样的生命线。而接受率取决于草稿模型和大模型的"相似度"。草稿模型和大模型的分布越接近,草稿猜的 token 越容易被接受。这就引出了几种不同的实现路线。

3.3 三种主流实现路线对比

路线草稿来源接受率额外显存适用场景
独立小模型单独训练的小模型中需加载草稿模型有同系列小模型可用
Medusa大模型加多个预测头中高少量(预测头)可微调模型
EAGLE特征层复用+轻量头高少量追求极致加速

独立小模型最简单,比如用 1B 模型给 70B 模型做草稿。但问题是小模型和大模型的分布差异大,接受率往往一般。

Medusa在大模型最后一层加几个并行的预测头,每个头预测未来第 2、3、4 个 token。因为共享了大模型的特征,接受率比独立小模型高。但需要微调预测头。

EAGLE是目前公认效果最好的,它不重新训练一个模型,而是在大模型的特征层上接一个轻量头,复用大模型已经算出来的特征来预测下一个 token 的特征。接受率通常能到 0.7 以上,加速比能到 3x 左右。

3.4 实操:在推理框架里开启投机采样

以 vLLM 为例,开启投机采样非常简单,但参数调优有讲究:

# 用独立小模型做草稿 python -m vllm.entrypoints.openai.api_server \ --model your-large-model \ --speculative-model your-draft-model \ --num-speculative-tokens 5 \ --tensor-parallel-size 2

num-speculative-tokens是每次草稿生成的候选数,这个参数很关键。设太小,收益不够;设太大,草稿模型的开销和验证失败的概率都会上升。我的经验是从 5 开始试,然后根据实测的接受率调整。如果接受率能稳定在 0.6 以上,可以往上加到 7-8;如果接受率低于 0.4,说明草稿模型和大模型差异太大,加多少都没用,得换草稿方案。

3.5 投机采样的隐藏成本与调优心得

成本一:草稿模型的显存占用。草稿模型虽然小,但也要占显存。如果你的显存本来就紧张,加载草稿模型可能挤掉 KV Cache 的空间,反而降低并发能力。这时候可以考虑 Medusa 或 EAGLE 这种"不额外加载完整模型"的方案。

成本二:验证失败的回滚。如果草稿猜的 token 被拒绝,需要回滚到最后一个被接受的 token 重新生成。这个回滚逻辑如果实现不好,会引入额外延迟。好在主流框架都处理好了,自己实现的话要特别注意。

心得:投机采样和量化叠加时,草稿模型最好也用相同的量化方案。我试过草稿模型用 FP16、大模型用 INT4,结果接受率明显下降,因为两者的数值分布差异被量化放大了。统一量化方案后,接受率回升了不少。

4. PD 分离:让预填充和解码各得其所

4.1 一个请求里藏着两种完全不同的负载

回到第 1 节讲的 Prefill 和 Decode。Prefill 是计算密集,需要大算力;Decode 是访存密集,需要大带宽。如果把它们放在同一张卡上跑,会发生什么?

假设你有一批请求同时到达。Prefill 阶段会把 GPU 算力吃满,这时候正在 Decode 的请求就被卡住了,token 生成速度骤降。反过来,当大量请求都在 Decode 时,GPU 算力闲置,新来的请求 Prefill 又要排队。两种负载互相干扰,谁也跑不痛快。

PD 分离(Prefill-Decode Disaggregation)的核心思想就是:把 Prefill 和 Decode 拆到不同的实例上跑。Prefill 实例专门做计算密集的预填充,Decode 实例专门做访存密集的解码。请求先送到 Prefill 实例算完 KV Cache,再把 KV Cache 传给 Decode 实例继续生成。

4.2 PD 分离真正解决的是什么问题

很多人以为 PD 分离是为了"更快",其实它主要解决的是资源利用率和尾延迟问题。

在混合部署下,一个长 prompt 的 Prefill 可能占用几百毫秒,这期间所有 Decode 请求都被拖慢,导致 TTFT(首 token 时间)和 TPOT(每 token 时间)的尾延迟都很差。PD 分离后,Prefill 和 Decode 互不干扰,各自的延迟都更稳定。

另一个收益是资源可以按需配比。Prefill 吃算力,那就配算力强的卡;Decode 吃带宽,那就配带宽大的卡。不用为了兼顾两者而妥协。在实际业务里,Prefill 和 Decode 的负载比例会随请求特征变化,分离部署让扩缩容也更灵活。

4.3 KV Cache 传输:PD 分离最大的工程挑战

PD 分离不是没有代价的,最大的代价就是KV Cache 要在 Prefill 和 Decode 实例之间传输。

KV Cache 有多大?一个 70B 模型,32 层,hidden size 8192,FP16 精度,每个 token 的 KV Cache 大约是 2 × 32 × 8192 × 2 字节 ≈ 1MB。一个 4K 上下文的请求,KV Cache 就有 4GB。要在实例间传 4GB 数据,如果走普通网络,延迟会非常可观。

所以 PD 分离对网络要求很高。实践中通常用高速互联(比如 NVLink、RDMA),传输延迟能压到毫秒级。如果网络带宽不够,KV 传输的开销可能吃掉分离带来的收益,那就得不偿失了。

4.4 什么场景该上 PD 分离,什么场景别碰

PD 分离不是银弹,它有明确的适用边界:

适合上的场景:

  • 请求量大、并发高,Prefill 和 Decode 互相干扰严重
  • prompt 普遍较长(长上下文场景),Prefill 开销占比高
  • 有高速互联网络,KV 传输不是瓶颈
  • 需要精细控制 TTFT 和 TPOT 的 SLA

别碰的场景:

  • 请求量小,单实例就能扛住,分离反而增加复杂度
  • 网络条件差,KV 传输开销大于收益
  • 团队运维能力有限,PD 分离的部署和调试成本不低

我的建议是:先把量化和投机采样做扎实,这两项收益直接、落地简单。等业务量真的上来了,Prefill 和 Decode 的干扰成为瓶颈时,再考虑 PD 分离。

4.5 部署 PD 分离时的参数与监控要点

如果决定上 PD 分离,有几个参数和监控指标必须盯紧:

  • KV 传输带宽利用率:这是 PD 分离的命脉。如果带宽利用率长期接近 100%,说明传输是瓶颈,要么升级网络,要么减少传输量(比如量化 KV Cache)。
  • Prefill 和 Decode 实例的比例:这个比例要根据实际负载动态调整。监控两个实例的 GPU 利用率,如果 Prefill 实例长期满载而 Decode 实例空闲,就该增加 Prefill 实例。
  • KV Cache 的量化:前面提过,KV Cache 量化到 INT8 能省一半传输量,对 PD 分离来说这是直接的收益。强烈建议在 PD 分离场景下开启 KV Cache 量化。

提示:PD 分离的调试比单机部署复杂得多,建议先用小规模集群验证,确认收益后再扩大。我见过不少团队一上来就大规模部署,结果被各种网络和同步问题搞得焦头烂额。

5. 三项技术如何组合:一份可落地的决策清单

5.1 按瓶颈选技术,而不是按热度选

三项技术不是越多越好,关键看你的瓶颈在哪。我整理了一份决策清单:

你的瓶颈优先上原因
显存不够,模型加载不下量化直接减少权重占用
单请求延迟高,吞吐还行投机采样减少 Decode 循环次数
并发高,尾延迟差PD 分离隔离 Prefill 和 Decode 干扰
长上下文,KV Cache 爆显存KV Cache 量化直接压缩 KV 占用
综合成本高量化 + 投机采样两项叠加收益最大

5.2 组合顺序与叠加效应

如果三项都要上,我的推荐顺序是:先量化,再投机采样,最后 PD 分离。

先量化的原因很简单:它落地最简单,收益最直接,而且量化后的模型显存占用小,为后续加载草稿模型、部署多实例腾出了空间。投机采样在量化之后上,注意草稿模型和大模型用统一的量化方案。PD 分离放最后,因为它对基础设施要求最高,等前两项把单机性能榨干之后,再考虑分布式拆分。

叠加时要注意收益不是简单相乘。量化让 Decode 变快,投机采样让 Decode 循环变少,两者叠加时,投机采样的接受率可能因为量化而略降,实际加速比会比单独测算的低一些。所以每上一项,都要重新测一遍端到端指标,别拿旧数据推算。

5.3 一套完整的验证流程

最后给一套我常用的验证流程,确保每项技术都真正带来了收益:

  1. 建立基线:FP16 模型,单实例,测出 TTFT、TPOT、吞吐、显存占用四个核心指标。
  2. 上量化:量化后重测四个指标,同时验证精度(PPL + 业务指标)。确认收益后再进入下一步。
  3. 上投机采样:在量化模型基础上开启,重点测接受率和端到端延迟。如果接受率低于 0.4,考虑换草稿方案。
  4. 上 PD 分离:小规模验证 KV 传输开销,确认网络不是瓶颈后再扩大。
  5. 回归测试:每步都保留上一版的配置,方便对比和回滚。

这套流程看起来繁琐,但能帮你避免"上了新技术反而变慢"的尴尬。我踩过最深的坑就是一次性把三项都上了,结果出问题时分不清是哪一项导致的,排查花了好几天。一次只改一个变量,这是性能优化最朴素也最有效的原则。

6. 我在实际部署中攒下的几条经验

量化这块,我最想强调的是别迷信工具给的默认参数。group_size、desc_act 这些参数对精度和速度的影响很大,一定要用自己的业务数据测。我见过有人直接用默认配置量化,结果在特定任务上精度掉了 5 个点,换了个 group_size 就恢复到 1 个点以内。

投机采样这块,接受率要持续监控。业务请求的分布会变,今天接受率 0.7,明天可能因为用户输入风格变化掉到 0.5。建议把接受率做成监控指标,低于阈值就告警,及时调整草稿策略。

PD 分离这块,网络是命门。上线前一定要做压力测试,模拟高并发下的 KV 传输,确认带宽和延迟都在可接受范围。我见过网络没测好就上线的,高峰期 KV 传输排队,延迟比不分离还差。

最后说个心态问题。推理加速是个持续优化的过程,没有一劳永逸的方案。模型在变、业务在变、硬件在变,今天的最优配置明天可能就不是了。保持测量、保持迭代,比追求某个"终极方案"实在得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询