尧图精选

大模型推理加速实战:量化、投机采样与PD分离的工程指南

🕒 发布时间:2026/10/1 4:44:15 📁 来源:尧图网络
大模型推理这件事真正跑过线上服务的人都知道训练只是前半场推理才是那个天天烧钱、天天被业务方催着降本的无底洞。一个70B级别的模型如果用FP16权重全量加载光显存就吃掉140GB两张80G的卡刚够塞下权重KV Cache和中间激活还没算进去。业务侧还要求首token延迟低于500ms、吞吐拉到每秒几百token这时候你会发现光靠堆卡是堆不出性价比的。量化、投机采样、PD分离这三样东西基本就是当前推理加速的三根支柱量化解决权重和计算太占资源的问题投机采样解决自回归解码一次只出一个token太慢的问题PD分离解决预填充和解码互相拖累、资源利用率上不去的问题。这篇内容我打算把这三块拆开揉碎讲清楚从原理到实操参数再到我踩过的坑适合已经跑过推理服务、想进一步压榨性能的工程师也适合刚接触推理优化、想建立完整认知框架的同学。1. 量化把权重从FP16压到INT8甚至INT4到底动了什么1.1 量化的本质是一次带误差的映射量化的核心动作是把一个连续的浮点数值域映射到一个离散的整数数值域上。以INT8为例FP16的权重范围可能是[-3.2, 3.1]我们要把它压到[-127, 127]这个整数区间。映射公式很朴素scale (max_val - min_val) / (q_max - q_min) zero_point q_min - round(min_val / scale) q round(x / scale) zero_point反量化的时候就是x_hat (q - zero_point) * scale。这里的关键在于x_hat和原始x之间必然存在误差因为round操作丢掉了小数部分。量化要做的所有工程优化本质上都是在让这个误差对最终模型输出的影响尽可能小。为什么INT8通常掉点很少而INT4就容易崩因为INT8有256个离散档位FP16的尾数有10位两者表达能力差距没那么夸张INT4只有16个档位对于权重分布比较分散的层量化误差会直接放大到输出上。我实测过一个13B模型INT8 weight-only量化后困惑度perplexity从5.62涨到5.71基本无感换成INT4的group-wise量化group size128困惑度涨到5.98还能接受但如果用per-tensor的INT4直接飙到7.3生成质量肉眼可见地变差。1.2 权重量化、激活量化、KV Cache量化是三件不同的事很多人一说量化就笼统地讲我把模型量化了但实际线上部署时你得区分清楚量化的是哪一部分因为它们的收益和代价完全不同。权重量化Weight-only Quantization是最常见的做法只把模型权重压成INT8或INT4计算时反量化回FP16再做矩阵乘。它的收益是显存占用直接砍半甚至砍到四分之一加载速度也快。代价是计算过程没有真正加速因为反量化有额外开销实际算力还是FP16的。适合显存瓶颈明显、算力相对充裕的场景。权重激活量化W8A8是把权重和激活值都量化成INT8这样矩阵乘可以用INT8的Tensor Core来算理论算力是FP16的2倍。但激活值的动态范围比权重难搞得多因为激活值跟输入数据强相关不同batch、不同序列长度下分布差异很大。所以W8A8通常需要做动态量化per-token或per-channel校准集的选择就很关键。KV Cache量化是长上下文场景的救命稻草。一个32K上下文的70B模型KV Cache能占到几十GB。把KV Cache从FP16压到INT8显存直接省一半能多塞好几个并发请求。但KV Cache量化对精度的影响比权重量化敏感尤其是attention score的计算量化误差会被softmax放大。量化类型显存收益算力收益精度风险适用场景Weight-only INT8约50%几乎无低显存瓶颈Weight-only INT4约75%几乎无中显存极度紧张W8A8约50%约2倍中算力瓶颈KV Cache INT8KV部分50%无中高长上下文高并发1.3 实操中量化校准集怎么选做W8A8量化的时候校准集calibration dataset的选择直接决定量化精度。我见过有人图省事直接拿几百条通用语料跑一遍就完事结果上线后特定领域的输出质量断崖式下跌。校准集的核心原则是分布要贴近真实线上流量。具体操作上我会从线上日志里采样500到1000条真实请求覆盖不同的输入长度、不同的业务类型。如果线上流量有长尾分布校准集里也要体现出来。校准的步数不用太多通常128到512个batch就够因为量化参数scale和zero_point的估计收敛很快。还有一个容易忽略的点校准时的序列长度要覆盖线上最大长度。如果你校准用的是512长度但线上跑的是8K长度激活值的分布会完全不一样量化误差会显著增大。我一般会把校准序列长度设成线上P99长度的1.2倍。提示量化校准不是一次性的工作。模型更新、业务流量变化后最好重新跑一遍校准否则精度会慢慢漂移。1.4 量化模型部署时的那些坑第一个坑是算子支持不全。你量化出来的模型推理引擎不一定所有算子都支持INT8。比如某些特殊的激活函数、自定义的attention变体可能只有FP16实现。这时候要么回退到FP16要么自己写kernel后者成本很高。部署前一定要用推理引擎的算子支持列表过一遍。第二个坑是量化格式不统一。不同框架导出的量化模型格式五花八门GPTQ、AWQ、GGUF、ONNX QDQ各有各的规范。跨框架迁移的时候经常出现权重对不上的问题。我建议在量化前就确定好目标推理引擎用它官方推荐的量化工具链别自己造轮子。第三个坑是精度验证不充分。很多人量化完只看困惑度觉得没涨多少就上线了。但困惑度是个平均指标它掩盖了特定能力上的退化。我一般会准备一套任务级的评测集覆盖问答、摘要、代码生成等场景量化前后逐项对比。曾经遇到过一个案例量化后困惑度只涨了0.05但代码生成的通过率掉了8个百分点这种问题只有任务级评测才能发现。2. 投机采样用一个小模型撬动大模型的解码速度2.1 自回归解码的串行瓶颈大模型推理慢根子在于自回归解码是串行的。生成第t个token必须等第t-1个token算完。这意味着GPU的并行算力在解码阶段根本吃不满大部分时间花在等待内存读取权重上。一个70B模型解码一个token要读140GB的权重FP16就算内存带宽是2TB/s光读权重就要70ms而实际计算量小得可怜。这就是所谓的memory-bound。投机采样Speculative Sampling的思路很巧妙既然大模型一次只能出一个token那我找个小模型先猜出接下来几个token然后让大模型一次性验证这几个token对不对。如果猜对了就相当于大模型一次生成了多个token如果猜错了就回退到第一个错误的位置。这样把串行的解码变成了并行验证大幅提升了GPU利用率。2.2 投机采样的数学保证为什么猜错了也不影响输出分布这是投机采样最精妙的地方。很多人担心小模型猜的token会不会改变大模型的输出分布答案是不会。投机采样有一套严格的接受-拒绝机制保证最终输出的分布和大模型单独解码的分布完全一致。具体来说假设小模型draft model对下一个token的预测概率是q(x)大模型target model的概率是p(x)。我们从小模型采样一个token x然后以概率min(1, p(x)/q(x))接受它。如果拒绝就从修正后的分布norm(max(0, p(x)-q(x)))中重新采样。数学上可以证明这样得到的样本服从p(x)分布。这个性质意味着投机采样是无损的它不会牺牲生成质量只是加速。这一点和量化不同量化是有损的投机采样是无损的。所以如果你的场景对精度要求极高投机采样是比量化更安全的选择。2.3 Draft模型怎么选不是越小越好选draft模型是投机采样的核心决策。直觉上大家会觉得draft模型越小越快但实际不是这样。draft模型太小预测准确率低大模型验证时频繁拒绝反而浪费了验证的开销。draft模型太大虽然准确率高但draft本身的解码开销也上去了。我实测下来的经验是draft模型和target模型的参数量比例在1:10到1:20之间比较合适。比如target是70Bdraft用3B到7B。另外draft模型最好和target模型同源比如同一个base模型蒸馏出来的这样两者的输出分布更接近接受率更高。还有一个技巧是用多层draft也就是用两个不同大小的draft模型级联。小draft先猜中等draft再猜最后target验证。这样在不同难度的情况下都能有不错的接受率。不过实现复杂度高收益提升有限一般场景用单draft就够了。Draft模型规模接受率实测单token加速比适用场景1B以下40%-55%1.3x-1.6x简单任务3B-7B65%-80%1.8x-2.5x通用场景13B80%-90%1.5x-2.0x复杂任务2.4 投机采样的参数调优speculative length怎么定投机采样有一个关键参数每次让draft模型猜多少个token也就是speculative length也叫lookahead。这个参数直接决定了加速效果。猜得太少比如只猜2个那验证的并行度不够加速有限。猜得太多比如猜10个draft模型后面几个token的准确率会急剧下降大部分都被拒绝浪费计算。我实测下来speculative length在4到6之间比较平衡。具体值要看draft模型的接受率曲线接受率高的可以设大一点。还有一个动态调整的策略根据历史接受率动态调整speculative length。如果最近几次接受率都很高就增大length如果接受率低就减小。这样能自适应不同的输入难度。vLLM和TensorRT-LLM都支持这种动态策略。注意投机采样的加速比不是线性的。当batch size增大时解码阶段逐渐从memory-bound变成compute-bound投机采样的收益会下降。所以投机采样最适合低batch、低并发的场景比如在线对话。高并发场景下还是得靠batching和PD分离。2.5 投机采样和量化的叠加效果这两个技术可以叠加使用而且叠加效果不错。量化降低了单次前向的显存和计算开销投机采样提升了并行度。我实测过一个组合70B模型做INT8权重量化draft用7B模型speculative length5在单请求场景下相比FP16无投机采样端到端加速比达到3.2倍。但叠加时要注意量化后的target模型和draft模型的分布差异可能变大导致接受率下降。所以如果要做量化投机采样最好让draft模型也做同样的量化保持分布一致性。3. PD分离把预填充和解码拆到不同机器上3.1 预填充和解码的资源需求完全不同大模型推理分两个阶段预填充Prefill和解码Decode。预填充是把整个输入prompt一次性过一遍模型计算出KV Cache这个阶段是compute-bound算力吃满显存带宽反而没那么紧张。解码是逐token生成每次只算一个token这个阶段是memory-bound算力闲置显存带宽是瓶颈。这两个阶段的资源需求差异巨大如果放在同一张卡上跑就会出现预填充时解码饿死解码时算力闲置的情况。尤其是在线服务请求是动态到达的长prompt的预填充会阻塞后面的解码请求导致首token延迟TTFT和token间延迟TPOT都很难看。PD分离Prefill-Decode Disaggregation的思路就是把预填充和解码拆到不同的机器或不同的GPU上各自独立调度。预填充集群专门处理prompt算完KV Cache后传给解码集群解码集群专门做逐token生成。这样两边都能按自己的资源特性做优化互不干扰。3.2 KV Cache的传输是PD分离的核心难点PD分离最大的工程挑战是KV Cache的传输。一个70B模型32K上下文的KV Cache大小大概是KV Cache size 2 * num_layers * num_kv_heads * head_dim * seq_len * dtype_size以Llama 2 70B为例80层8个KV headGQAhead_dim128seq_len32768FP162 * 80 * 8 * 128 * 32768 * 2 bytes 10.7 GB10.7GB的数据要在预填充节点和解码节点之间传输。如果走PCIe 4.0 x16理论带宽32GB/s实际能到20GB/s左右传输耗时约0.5秒。如果走网络比如100Gbps网卡理论12.5GB/s实际8GB/s左右传输要1.3秒。这个延迟对于TTFT来说是致命的。所以PD分离的部署预填充和解码节点之间的互联带宽是关键。同机多卡用NVLink最好跨机的话至少要用高速网络。如果带宽不够KV Cache传输的延迟会吃掉PD分离带来的所有收益。3.3 实际部署中的调度策略PD分离的调度比单体部署复杂得多。核心要解决两个问题预填充请求怎么分配到预填充节点解码请求怎么分配到解码节点以及KV Cache怎么路由。我实践下来比较有效的策略是分层调度。预填充层用最短队列优先Shortest Queue First因为预填充的计算时间跟prompt长度强相关短prompt先处理能降低平均TTFT。解码层用连续批处理Continuous Batching把不同请求的解码步骤合并成一个batch提升GPU利用率。KV Cache的路由要保证同一个请求的预填充和解码在配对的节点上。通常会在预填充节点和解码节点之间维护一个映射表预填充完成后根据解码节点的负载情况选择一个节点把KV Cache传过去。这里有个优化点如果预填充节点和解码节点在同一台机器上KV Cache可以通过共享内存传递省掉网络传输。调度策略优点缺点适用场景最短队列优先降低平均TTFT长prompt可能饿死短prompt为主轮询实现简单负载不均请求均匀负载感知负载均衡好实现复杂大规模集群亲和性调度减少KV传输可能负载不均同机多卡3.4 PD分离的收益边界什么时候不值得做PD分离不是银弹它有明确的适用边界。如果你的服务满足以下条件PD分离的收益可能覆盖不了它的复杂度请求量很小单卡就能扛住没有资源争抢prompt都很短预填充开销可以忽略对TTFT要求不严格可以容忍预填充阻塞集群规模小没有独立的预填充和解码资源池我一般建议当单卡QPS超过5或者prompt长度P99超过2K或者TTFT的P99要求低于1秒时才考虑上PD分离。否则用连续批处理chunked prefill就能解决大部分问题。chunked prefill是个折中方案把长prompt的预填充切成多个chunk每个chunk和decode请求混在一个batch里跑。这样既不会让预填充阻塞解码又不需要拆机器。实现上比PD分离简单得多收益在中等规模场景下也很可观。3.5 PD分离和量化的协同PD分离场景下量化的收益会被放大。因为预填充节点和解码节点的资源瓶颈不同量化对两者的收益也不同。预填充是compute-boundW8A8量化能直接提升算力缩短预填充时间。解码是memory-bound权重量化能减少显存带宽压力提升解码速度。我实测过一个配置预填充节点用W8A8量化解码节点用INT4权重量化KV Cache INT8。相比全FP16的PD分离整体吞吐提升了2.1倍TTFT降低了35%。这个组合的关键是预填充对精度敏感度低因为只算一次可以用更激进的量化解码对精度敏感度高因为误差会累积量化要保守一些。4. 三套技术的组合拳怎么根据场景选型4.1 先定位瓶颈再选技术推理加速最忌讳的就是别人用什么我就用什么。量化、投机采样、PD分离各自解决不同的问题选错了不仅没收益还会增加复杂度。我的选型逻辑是这样的先看显存是不是瓶颈。如果模型加载后显存剩余不足20%优先上权重量化。再看算力是不是瓶颈。如果GPU利用率长期低于50%说明是memory-bound优先上投机采样或KV Cache量化。最后看调度是不是瓶颈。如果TTFT和TPOT的P99波动很大说明预填充和解码在互相干扰考虑PD分离或chunked prefill。瓶颈类型判断指标首选技术次选技术显存不足显存利用率90%权重量化KV Cache量化算力闲置GPU利用率50%投机采样增大batch调度干扰TTFT/TPOT波动大chunked prefillPD分离长上下文KV Cache占比50%KV Cache量化PD分离4.2 一个真实的组合案例我经手过一个在线客服场景模型是13B平均prompt长度800平均输出长度200QPS峰值15。最初的部署是单机双卡FP16TTFT的P99是2.3秒TPOT的P99是180ms业务方不满意。第一步上了INT8权重量化显存从26GB降到14GB单卡能塞下模型了TTFT降到1.8秒。第二步加了KV Cache INT8量化显存进一步降到11GBbatch size从4提到8TPOT降到120ms。第三步上了投机采样draft用1.5B模型speculative length4接受率72%TPOT降到75ms。第四步因为QPS上来了单机双卡开始出现预填充阻塞上了chunked prefillTTFT的P99降到1.1秒。最终配置INT8权重量化 KV Cache INT8 投机采样 chunked prefillTTFT的P99从2.3秒降到1.1秒TPOT的P99从180ms降到75ms单机吞吐从8 QPS提到22 QPS。整个过程没有上PD分离因为chunked prefill已经解决了调度问题PD分离的复杂度不值得。4.3 组合时的相互影响这几个技术组合时不是简单叠加它们之间有相互影响。量化会影响投机采样的接受率。量化后的target模型输出分布会有微小偏移如果draft模型没做同样的量化接受率会下降。我实测过target做INT8量化、draft不做量化接受率从75%降到62%。所以要么两者都量化要么都不量化。量化也会影响PD分离的KV Cache传输量。KV Cache量化后传输的数据量减半传输延迟也减半。这在跨机PD分离场景下收益很明显。投机采样和PD分离的协同比较微妙。投机采样提升了解码速度意味着解码节点能处理更多请求可能会加剧预填充节点的压力。所以如果同时上这两个技术预填充和解码的资源配比要重新调。4.4 精度验证的完整流程不管上哪个技术精度验证都是必须的。我一般分三层验证第一层是困惑度对比快速筛掉明显有问题的配置。困惑度涨幅超过5%就要警惕。第二层是任务级评测用业务相关的评测集覆盖主要场景。这一层能发现困惑度掩盖的问题。第三层是在线A/B测试小流量灰度对比业务指标比如客服场景的解决率、用户满意度。这一层最真实但成本也最高。三层都过了才能全量上线。我见过太多团队跳过第二层直接上线结果被业务方投诉生成质量下降回头排查发现是量化校准集没覆盖某个业务场景。提示精度验证要固定随机种子否则生成结果的波动会干扰判断。另外评测集要定期更新避免模型对评测集过拟合。5. 工程落地中的几个反直觉发现5.1 量化不一定省时间但一定省显存很多人以为量化后推理会变快实际上权重量化weight-only在不少场景下反而变慢因为反量化有额外开销而且INT8的矩阵乘如果没有专门的kernel优化可能还不如FP16。量化的核心收益是显存显存省下来能塞更大的batch间接提升吞吐。所以如果你的瓶颈是算力而不是显存权重量化帮不上忙得用W8A8。5.2 投机采样的加速比和batch size成反比这个前面提过但值得再强调。投机采样在batch size1时加速比最高能到2到3倍。batch size增大后解码阶段逐渐变成compute-bound投机采样的并行验证优势被稀释加速比可能降到1.2倍甚至更低。所以投机采样最适合在线低并发场景高并发场景下batching的收益更大。5.3 PD分离的收益在长prompt场景才明显如果prompt都很短比如平均100 token预填充开销很小PD分离的收益微乎其微反而增加了KV Cache传输的开销。PD分离的收益在prompt长度超过1K、且请求混合了长短prompt时才明显。短prompt场景用chunked prefill就够了。5.4 KV Cache量化对长上下文的影响是非线性的KV Cache量化在短上下文下几乎无感但上下文越长量化误差累积越严重。我实测过4K上下文下KV Cache INT8的困惑度涨幅是0.0232K上下文下涨到0.15。所以长上下文场景做KV Cache量化要么用更细粒度的量化per-channel要么保留部分层不量化。6. 从实验到生产的检查清单把这三套技术从实验推到生产我总结了一份检查清单每次上线前过一遍能避开大部分坑。量化相关校准集是否覆盖线上主要场景和长度分布推理引擎是否支持所有量化算子量化格式是否和目标引擎匹配任务级评测是否通过是否有回退到FP16的预案投机采样相关draft模型和target模型是否同源speculative length是否根据接受率动态调整接受率是否在合理区间60%以上高并发场景下加速比是否仍然为正draft模型的显存开销是否可接受PD分离相关预填充和解码节点之间的带宽是否足够KV Cache传输是否有压缩或量化调度策略是否适配请求分布是否有降级到单体部署的预案监控是否覆盖TTFT、TPOT、KV传输延迟通用是否有完整的性能基线TTFT、TPOT、吞吐、显存是否有精度基线困惑度、任务指标是否有灰度发布和回滚机制监控告警是否覆盖关键指标这份清单不是摆设我每次上线前都会逐项确认。有一次就是因为漏了推理引擎算子支持这一项上线后发现某个自定义attention算子没有INT8实现整个量化模型跑不起来临时回退浪费了两个小时。7. 我个人在实际操作中的几点体会做推理加速这几年最大的体会是没有银弹只有权衡。量化省显存但可能掉精度投机采样加速但增加复杂度PD分离提升资源利用率但引入传输开销。每个技术都有它的适用边界关键是先定位清楚自己的瓶颈在哪。第二个体会是先做简单的再做复杂的。很多团队一上来就想上PD分离结果发现chunked prefill就能解决问题。先上量化再上投机采样最后考虑PD分离这个顺序在大多数场景下都是合理的。每上一步都要有明确的性能收益和精度验证不要为了技术而技术。第三个体会是监控比优化更重要。你优化了半天如果没有完善的监控根本不知道优化有没有效果也不知道瓶颈转移到了哪里。TTFT、TPOT、GPU利用率、显存利用率、KV Cache命中率这些指标要实时可见。我见过太多团队优化完不监控结果线上出问题排查半天。最后一个体会是精度验证要贯穿始终。推理加速的所有技术最终都要服务于生成质量。加速比再高如果生成质量下降业务方也不会买账。所以精度验证不是上线前的一道关卡而是贯穿整个优化过程的持续动作。每次改配置都要跑一遍精度验证确保没有退化。这套东西说起来复杂但真正跑通一遍之后你会发现推理加速的收益是实打实的。一个配置调优好的推理服务相比朴素部署成本能降一半以上延迟能降一个数量级。这个投入产出比值得花时间去啃。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →