大模型推理优化实战:量化、推测解码与PagedAttention的工程取舍

发布时间:2026/10/9 22:38:28
大模型推理优化实战:量化、推测解码与PagedAttention的工程取舍 1. 推理优化到底在优化什么从一次线上延迟抖动说起模型层推理优化这件事很多人第一反应是“上量化”“换推理引擎”“加缓存”但真到线上环境里你会发现延迟抖动往往不是单一因素造成的。我印象很深的一次排查同一个模型、同一批请求白天 P99 延迟稳定在 800ms 左右到了晚上高峰期突然飙到 3s 以上GPU 利用率却只有 60% 出头。当时第一反应是算力不够准备扩容但仔细看监控才发现显存占用已经接近上限batch size 被迫压得很小GPU 大部分时间在等内存搬运而不是在算。这就是推理优化最核心的矛盾算力、显存、延迟、吞吐这四个指标互相拉扯。你增大 batch 能提升吞吐但显存不够就会 OOM你量化权重能省显存但可能引入精度损失你用更激进的并行策略能降延迟但通信开销又会吃掉收益。所以做推理优化第一步不是急着选工具而是先搞清楚当前系统的瓶颈到底在哪。这一章我们聚焦模型层的推理优化主要覆盖四条技术路线量化、推测解码、PagedAttention 以及算子与调度层面的优化。这四块不是孤立的实际工程里往往是组合使用。比如一个典型的部署方案可能是权重用 INT8 量化 KV Cache 用 PagedAttention 管理 投机采样加速解码 算子融合减少 kernel launch 开销。每一块解决不同层面的问题叠加起来才能把推理成本压到可接受的范围。适合读这一章的人我大致分三类一是刚接触模型部署、想知道推理优化有哪些抓手的新手二是已经在做推理服务、但遇到性能瓶颈不知道怎么下手的工程师三是需要做技术选型、评估不同方案成本收益的架构同学。不管你是哪一类我都建议先建立一个基本认知推理优化的本质是在给定硬件约束下找到延迟和吞吐的最优平衡点所有技术手段都是为这个目标服务的。下面我会按“先讲清楚每项技术解决什么问题、再讲怎么落地、最后讲踩过的坑”这个顺序展开。不会堆砌论文公式而是尽量用工程视角把每个决策背后的取舍讲明白。2. 量化省显存和提速的第一抓手但精度账要算清楚2.1 量化到底在做什么为什么它能同时省显存和提速量化的本质是把模型权重和激活值从高精度浮点数比如 FP16、FP32映射到低精度表示比如 INT8、INT4。举个直观的例子FP16 每个参数占 2 字节INT8 只占 1 字节INT4 更是只占 0.5 字节。一个 70 亿参数的模型FP16 下光权重就要 14GB 显存INT8 降到 7GBINT4 只要 3.5GB。显存省下来就能塞更大的 batch或者把模型塞进更小的卡里。但量化不只是省显存。现代 GPU 上INT8 矩阵乘法的理论吞吐通常是 FP16 的 2 倍左右因为整数运算单元更密集、数据搬运量更小。实际加速比取决于你的 kernel 实现和硬件架构通常在 1.3 到 1.8 倍之间。注意这里说的是“理论吞吐”实际能不能吃到这个收益还要看你的瓶颈是不是在计算上。如果瓶颈在内存带宽量化省下的带宽反而可能带来更大收益。量化的粒度也很关键。Per-tensor 量化是整个张量共用一个缩放因子实现简单但精度损失大Per-channel 量化是每个通道一个缩放因子精度好很多Group-wise 量化比如每 128 个元素一组在 INT4 场景下几乎是标配因为 INT4 的动态范围太窄不做分组精度会崩。我在实际项目里INT8 一般用 per-channel 就够了INT4 基本都会上 group-wisegroup size 取 128 或 64。2.2 PTQ 和 QAT 怎么选大多数场景先做 PTQ 就够了量化分两条路训练后量化PTQ和量化感知训练QAT。PTQ 是拿训练好的模型直接量化不需要重新训练成本低、上手快QAT 是在训练过程中模拟量化误差让模型学会适应低精度精度通常更好但需要训练资源和数据。我的经验是INT8 PTQ 在绝大多数场景下精度损失可以忽略尤其是用 per-channel 加校准集的情况下。校准集不需要很大几百条代表性样本就够但一定要覆盖真实分布的多样性。我见过有人拿训练集前 100 条做校准结果线上遇到长文本就崩因为校准集里全是短句激活值的动态范围估计偏了。INT4 就不一样了PTQ 往往会有明显掉点尤其是小模型或者对精度敏感的任务。这时候要么上 QAT要么用更先进的 PTQ 方法比如 GPTQ、AWQ 这类基于权重重要性的方法。GPTQ 的思路是逐层量化用 Hessian 矩阵指导哪些权重更重要、需要保留更高精度AWQ 则是观察到激活值里有一小部分“显著通道”对这些通道做保护。这两种方法在开源社区都有成熟实现INT4 下能把精度损失压到 1% 以内。提示量化前一定要先跑一遍 baseline把 FP16 下的精度指标记下来。量化后再跑同一套评测对比掉点。没有 baseline 的量化就是盲人摸象。2.3 量化落地的完整流程与实测数据我拿一个实际项目举例模型是 13B 级别的对话模型硬件是单卡 24GB。FP16 下权重占 26GB根本放不下必须量化。流程大致是这样确定量化方案权重 INT4 group-wisegroup size 128激活 INT8 per-token 动态量化。选这个组合是因为权重占大头压到 INT4 收益最大激活用 INT8 是因为动态量化不需要校准集实现简单。选择工具用 GPTQ 做权重量化推理时用支持 INT4 的 kernel。这里要注意不是所有推理框架都支持 group-wise INT4选型时要确认。校准与评测准备 512 条覆盖多轮对话、长文本、代码等场景的校准数据量化后在自建评测集上对比。精度对比FP16 baseline 准确率 78.3%INT4 量化后 77.1%掉点 1.2 个百分点。这个幅度在可接受范围内因为对话任务对轻微精度损失不敏感。性能实测显存占用从 26GB 降到 8.5GBbatch size 从 1 提到 8吞吐提升约 5 倍单请求延迟从 1.2s 降到 0.9s。这里有个细节值得说量化后首 token 延迟TTFT和解码延迟的变化趋势可能不一样。TTFT 主要受 prefill 阶段影响这个阶段是计算密集型的INT4 的加速比较明显解码阶段是内存带宽密集型的量化省带宽的收益更大。所以如果你的场景是长输入短输出量化收益主要在 TTFT如果是短输入长输出收益主要在解码吞吐。2.4 量化踩坑实录那些文档里不会写的细节第一个坑是量化格式和推理框架不匹配。我遇到过用 A 工具量化出来的模型B 框架加载后精度暴跌排查半天发现是缩放因子的排列顺序不一致。不同工具对 group-wise 量化的存储布局可能有差异跨工具使用时一定要先做小规模验证。第二个坑是动态量化的开销。激活用动态量化时每次推理都要实时计算缩放因子这个开销在小 batch 下可能抵消掉量化带来的收益。实测下来batch size 小于 4 的时候动态量化的额外开销能占到总延迟的 10% 以上。解决办法要么是改用静态量化需要校准集要么是增大 batch。第三个坑是量化对某些层的破坏性特别大。比如 LayerNorm 层、embedding 层这些层对精度敏感量化后容易出问题。常见做法是这些层保持 FP16只量化线性层。这个混合精度的策略在大多数框架里都支持配置时留意一下。第四个坑是INT4 的 kernel 支持不完整。有些框架宣称支持 INT4但只支持特定 shape 或特定硬件。我踩过一次模型在 A100 上跑得好好的换到消费级卡上直接报错因为那个 kernel 只针对特定架构优化过。选型时一定要在目标硬件上实测。3. 推测解码用一个小模型给大模型“打草稿”3.1 推测解码的核心思想为什么小模型能加速大模型推测解码Speculative Decoding这个思路第一次看会觉得反直觉用一个小模型去加速一个大模型小模型本身也要算怎么会更快关键在于大模型解码是内存带宽瓶颈不是计算瓶颈。解码阶段每生成一个 token都要把整个模型的权重从显存读一遍计算量却很小。也就是说GPU 的算力大量闲置时间都花在搬数据上了。推测解码的做法是先用一个小模型draft model快速生成 K 个候选 token然后让大模型target model一次性验证这 K 个 token。验证是并行的一次前向就能算完 K 个位置的概率。如果小模型猜得准大模型一次前向就能确认多个 token相当于把 K 次串行解码压缩成 1 次并行验证。小模型虽然也要算但它小得多开销可以忽略。这里的关键指标是接受率acceptance rate也就是小模型猜的 token 里有多少被大模型认可。接受率越高加速越明显。理论上如果接受率是 α平均每次能确认的 token 数是 (1-α^(K1))/(1-α)加速比大致是这个数除以 (1 K×cost_ratio)其中 cost_ratio 是小模型和大模型单次前向的开销比。3.2 草稿模型怎么选不是越小越好选草稿模型有几个考量。第一是分布要接近草稿模型和目标模型的能力差距不能太大否则接受率会很低。实践中常用同系列的小模型比如目标模型是 13B草稿模型用 1B 或 3B 的同架构模型。第二是速度要够快草稿模型本身不能太慢否则验证的收益被草稿开销吃掉。第三是显存要放得下草稿模型和目标模型要同时驻留显存。我实测过几组搭配数据大致是这样目标模型 13B草稿模型 1BK4 时接受率约 0.72加速比 1.9 倍草稿模型换成 3B接受率提到 0.81但草稿开销增加加速比反而降到 1.6 倍。所以草稿模型不是越大越好要找到接受率和开销的平衡点。还有一种不需要额外草稿模型的方案叫自推测解码Self-Speculative Decoding用目标模型自己的浅层或部分层做草稿。这种方案省显存但接受率通常不如独立草稿模型。另外还有Medusa这类方案在目标模型上加几个预测头一次预测多个位置的 token思路类似但实现不同。3.3 推测解码的工程落地与参数调优落地推测解码核心是调好 K 值每次猜多少个 token。K 太小加速有限K 太大草稿开销增加而且后面的 token 接受率会下降。经验值是 K 取 4 到 8 之间具体要看接受率曲线。我一般会先跑一组实验测不同 K 下的实际加速比选峰值点。另一个参数是采样策略。推测解码要保证输出分布和原始模型一致所以验证阶段不能简单取 argmax而是要用一种叫“拒绝采样”的方法。具体来说对每个候选 token计算目标模型和草稿模型的概率比以一定概率接受。这个实现细节如果搞错输出分布就偏了生成质量会下降。好在主流推理框架都封装好了自己实现的话要仔细对照论文。注意推测解码在 batch size 较大时收益会下降因为大 batch 下解码本身就不是纯内存带宽瓶颈了计算占比上升草稿模型的额外计算会拖后腿。所以推测解码更适合低并发、低延迟的场景。3.4 推测解码的适用边界什么时候不该用推测解码不是万能的。第一高并发场景收益有限前面说了大 batch 下瓶颈转移草稿开销变成负担。第二输出多样性高的任务接受率低比如创意写作、开放式对话草稿模型很难猜准。第三显存紧张时放不下两个模型这时候要么放弃要么用自推测方案。我踩过的一个坑是在 batch size 动态变化的服务里推测解码的收益波动很大。低峰期 batch1加速 1.8 倍高峰期 batch16加速只有 1.1 倍有时候甚至是负优化。后来我们的做法是做一个动态开关根据当前 batch size 决定是否启用推测解码。这个策略在实际服务里效果不错。4. PagedAttention把 KV Cache 的显存浪费挤出来4.1 KV Cache 为什么是显存大户要理解 PagedAttention先要理解 KV Cache 为什么重要。自回归解码时每生成一个 token都要用到之前所有 token 的 Key 和 Value。如果每次都重新算计算量会随序列长度平方增长。所以标准做法是把历史 token 的 K、V 缓存下来每次只算新 token 的 K、V然后和缓存拼接。这就是 KV Cache。问题在于KV Cache 的大小和序列长度成正比。一个 13B 模型如果 hidden size 是 5120层数 40那么每个 token 的 KV Cache 大约是 2 × 40 × 5120 × 2 字节 1.6MBFP16。序列长度 2048 时单个请求的 KV Cache 就要 3.2GB。如果并发 10 个请求就是 32GB比模型权重还大。传统做法是给每个请求预分配一块连续显存大小按最大序列长度算。但实际序列长度往往远小于最大值这就造成大量浪费。更麻烦的是预分配的连续块会导致显存碎片明明总空闲显存够却因为没有连续的大块而分配失败。实测中传统方案的显存利用率经常只有 20% 到 40%。4.2 PagedAttention 的分页思路像操作系统管理内存一样管理 KV CachePagedAttention 的核心思路借鉴了操作系统的虚拟内存分页。它把 KV Cache 切成固定大小的块block比如每块存 16 个 token 的 KV。每个请求的 KV Cache 不再要求连续而是由一组 block 组成通过一个块表block table来索引。这样带来几个好处第一消除内部碎片。传统方案按最大长度预分配实际用多少算多少浪费严重。分页后按需分配 block用多少给多少最后一个 block 最多浪费 15 个 token 的空间。第二消除外部碎片。block 是固定大小的任何空闲 block 都能用不会出现“总空间够但没有连续大块”的情况。第三支持共享。多个请求如果有相同的前缀比如相同的 system prompt可以共享前缀部分的 block只读不写省显存。实测数据很能说明问题同样一张 24GB 卡传统方案最多并发 8 个 2048 长度的请求PagedAttention 能并发到 20 个以上吞吐提升 2 到 3 倍。这个提升不是来自计算优化纯粹是把浪费的显存利用起来了。4.3 分页带来的调度新问题block 管理和抢占分页不是没有代价的。第一block 表的维护有开销每次分配、释放、查找都要操作元数据。不过这个开销相对推理本身可以忽略。第二attention 计算要适配分页布局不能再用简单的连续内存假设需要专门的 kernel。好在主流框架都实现了自己写的话要参考相关实现。第三也是最重要的是抢占preemption策略。当显存不够时需要把某些请求的 block 换出swap out到 CPU 内存或者直接丢弃重算。换出到 CPU 再换回来走 PCIe 带宽延迟很高丢弃重算则是把已生成的 token 重新跑一遍 prefill计算开销大。两种策略各有适用场景换出适合序列长、重算成本高的情况重算适合序列短、换出开销大的情况。我在实际调优中发现抢占策略对 P99 延迟影响很大。如果策略太激进频繁换出换入P99 会明显恶化。建议根据业务特点调参延迟敏感的场景宁可多占显存也不要频繁抢占吞吐优先的场景可以激进一些用抢占换更高的并发。4.4 PagedAttention 的实测调优经验几个实操要点。block size 的选择太小则 block 表庞大、管理开销高太大则内部碎片增加。常用值是 16也有用 8 或 32 的建议实测对比。前缀共享的收益如果业务里大量请求共享 system prompt开启前缀共享能省不少显存。我测过一个场景system prompt 占 500 token共享后显存节省约 15%。和量化的配合KV Cache 也可以量化INT8 的 KV Cache 能再省一半显存但要注意精度影响长序列下累积误差可能放大。还有一个容易忽略的点PagedAttention 和连续批处理continuous batching是绝配。连续批处理让不同请求在不同时间加入和退出 batch传统 KV Cache 方案下这种动态性很难处理分页后每个请求独立管理 block加入退出都很自然。两者结合才能把 GPU 利用率真正拉满。5. 算子融合与调度那些不起眼但收益稳定的优化5.1 算子融合为什么能省时间深度学习模型推理时每一层往往由多个算子组成比如 Linear Bias Activation。每个算子单独执行时都要把数据从显存读到寄存器算完再写回显存。算子融合就是把多个算子合并成一个 kernel中间结果留在寄存器或共享内存里不落显存。这样省的是内存带宽和 kernel launch 开销。以常见的 LayerNorm 为例它包含均值、方差、归一化、缩放、平移多个步骤。不融合的话每个步骤都是一次显存读写融合后一次读写搞定。实测中LayerNorm 融合能省 30% 到 50% 的该层耗时。再比如 Attention 里的 QK^T、softmax、PV 三个步骤融合成一个 FlashAttention kernel显存读写从 O(N²) 降到 O(N)长序列下收益巨大。5.2 连续批处理让 GPU 不再空转连续批处理Continuous Batching解决的是传统静态 batch 的浪费问题。静态 batch 下一个 batch 里所有请求必须等最长的那个生成完才能一起返回短请求早就结束了但 GPU 还得为它保留计算资源。连续批处理则是每个请求独立管理生成完就退出新请求随时加入GPU 始终在处理有效工作。这个优化的收益在高并发、请求长度差异大的场景下特别明显。我测过一个混合负载一半请求输出 50 token一半输出 500 token。静态 batch 下 GPU 利用率只有 45%连续批处理后提到 85% 以上吞吐翻倍。实现上连续批处理需要配合 PagedAttention 管理 KV Cache还需要调度器支持动态 batch 组装。5.3 调度层面的取舍优先级、超时与降级调度策略是推理服务里最容易被忽视、但对用户体验影响最大的一环。几个关键决策优先级队列VIP 请求优先处理普通请求排队超时控制超过一定时间的请求直接返回部分结果或错误避免拖垮整体降级策略高峰期自动切换到小模型或降低 max_tokens。我踩过的坑是早期没做超时控制一个超长请求把整个 batch 卡住导致后面所有请求 P99 爆炸。后来加了 per-request 超时超时后强制结束并返回已生成内容整体稳定性好了很多。另一个坑是优先级反转低优先级请求先到但一直占着资源高优先级请求反而排队。解决办法是用抢占式调度高优先级请求来了可以打断低优先级。6. 组合拳怎么打一个真实部署方案的取舍过程6.1 场景约束与目标拆解说一个我实际做过的项目。业务是智能客服模型 13B硬件是 2 张 24GB 卡。约束条件单请求延迟 P95 不超过 1.5s峰值 QPS 50显存要留出余量应对突发。目标是在这个约束下把成本压到最低。先算账13B 模型 FP16 权重 26GB单卡放不下必须量化或分卡。分卡的话通信开销大延迟难保证所以优先量化。INT8 权重 13GB单卡能放下但 KV Cache 还要占空间并发上不去。INT4 权重 6.5GB留出 17GB 给 KV Cache 和其他开销并发空间大很多。所以权重定 INT4。6.2 方案组合与参数确定最终方案是权重 INT4 group-wise KV Cache INT8 PagedAttention 连续批处理。推测解码试过但客服场景输出较短平均 80 token草稿模型收益不明显反而增加复杂度所以没上。参数方面block size 取 16max batch size 根据显存动态调整初始设 32。KV Cache 量化用 per-token 动态量化实测精度损失在可接受范围。连续批处理的调度窗口设为 10ms平衡延迟和吞吐。6.3 实测结果与调优迭代上线后实测P95 延迟 1.1s峰值 QPS 跑到 65单卡就能扛住另一张卡做冗余。显存占用稳定在 20GB 左右留有余量。对比 FP16 单卡方案QPS 只有 15 左右成本降到原来的四分之一。迭代过程中发现两个问题一是 KV Cache 量化在超长序列超过 1500 token下精度下降明显后来对超长请求做了特殊处理KV Cache 保持 FP16二是连续批处理的调度窗口在低峰期造成不必要的延迟后来改成动态窗口低峰期缩小到 2ms。7. 我在这几条路线里踩过的坑和总结的经验量化这块最大的教训是不要迷信论文指标。论文里的精度对比往往在特定数据集上你的业务数据分布可能完全不同。一定要用自己的评测集验证而且要覆盖边界情况。另外量化后的模型要重新做一轮压力测试因为低精度下的数值稳定性可能不同极端输入下更容易出问题。推测解码我的建议是先小规模验证再全量上线。接受率这个指标很依赖具体业务别人的数据参考价值有限。而且推测解码对框架版本敏感升级框架时要重新验证。我遇到过一次框架升级后接受率从 0.75 掉到 0.5排查发现是新版本的验证逻辑改了。PagedAttentionblock size 和抢占策略要一起调。这两个参数互相影响单独调一个往往找不到最优。建议做一个二维的参数扫描虽然费时间但能找到真正的甜点区。另外前缀共享的收益和业务强相关如果请求之间没有共享前缀这个功能开了也没用。算子融合和调度收益稳定但容易被忽视。很多团队把精力都放在量化和新算法上忽略了这些基础优化。实际上一个配置良好的连续批处理加算子融合能带来 1.5 到 2 倍的吞吐提升而且没有精度风险。我的建议是先把这些基础打牢再考虑激进的量化或推测解码。最后说一个心态问题推理优化没有银弹所有方案都是取舍。量化省显存但可能掉精度推测解码降延迟但增加复杂度PagedAttention 提吞吐但引入调度开销。做决策时要把业务约束放在第一位而不是追求某个指标的最优。我见过太多团队为了追求极致的吞吐把延迟做到不可接受最后用户流失得不偿失。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询