大模型推理投机解码与吞吐优化落地

日期:2026-08-02

一、项目背景

我们团队自托管了一套面向内部业务的大模型推理服务,底座用的是主流推理框架、跑在几张国产推理卡上。上线初期体验尚可,但随着业务方把更多场景接进来——智能客服、合同审阅、代码辅助——并发一上来问题就暴露了。最直观的是首字延迟(TTFT)高,用户发个问题要等好几秒才出第一个字;并发稍高,GPU 利用率看着满,有效吞吐却上不去,排队越积越长,最后雪崩式超时。

我们做了一次性能剖析,结论很扎心:瓶颈不在模型本身,而在推理调度。KV 缓存没有好好复用,长文本生成把显存占满后触发抢占,连续批处理(continuous batching)虽然开了但批效率不稳定,单请求占用算力的时间被拖长。换句话说,硬件没榨干,调度拖了后腿。

二、落地场景

优化围绕"降首字、提吞吐、省显存"三条线展开。第一是投机解码(speculative decoding):用一个轻量草稿模型先快速"猜"出后续若干 token,再由主模型一次性验证,命中即采纳,相当于用便宜的小模型算力换主模型的首字和步进延迟。第二是连续批处理调优:把请求的动态到达、完成、抢占做成更细粒度的批调度,缩短每批的"空转"时间。第三是 KV 缓存分页与复用:借鉴分页思想管理 KV 缓存,支持跨请求的 prefix 复用与抢占后的快速恢复,降低显存碎片。第四是显存与并发的平衡调参:根据卡型和序列长度分布,动态设定最大批大小与预留显存,避免 OOM 引发的级联重试。

三、关键技术挑战与解决思路

第一个挑战是草稿模型命中率。投机解码的收益完全取决于草稿猜得准不准。我们没直接用随机小模型,而是针对业务语料做了轻量微调,让草稿模型更贴近主模型的输出分布;同时限制投机步数(如 4–5 个 token),步数太长验证成本反而超过收益。命中率从初始约 0.6 提升到约 0.82 后,收益才真正显现。

第二个挑战是连续批处理的抢占与恢复。长请求和短请求混跑时,长请求占着显存不释放会饿死短请求。我们实现了一个基于优先级的抢占策略:短请求优先调度,长请求在显存压力下被换出 KV 到主机内存,恢复时从分页缓存快速 reload,避免从头重算。这要求 KV 缓存必须是分页可迁移的,不能和固定显存块绑死。

第三个挑战是 KV 缓存分页复用。我们把 KV 缓存切成固定大小的页,请求按注意力层的实际占用动态分配页,释放的页进全局池。对于多请求共享相同 system prompt 的场景,prefix 页可以直接复用,省下大量重复计算。这步对"同一模板多用户"类业务(如批量合同审阅)效果尤其明显。

第四个挑战是显存与并发的动态平衡。我们做了个自适应控制器:监控实时显存占用和排队长度,当排队陡增时适度下调单批最大序列数(保延迟),当显存充裕且请求短小时上调(提吞吐),避免人工拍脑袋定死参数导致的资源浪费或 OOM。

案例片段(已脱敏): 投机解码配置片段:speculate: {draft_model: "tiny-1.3b", num_speculate: 5, verify_with: "main-13b", max_draft_mismatch: 1}。连续批处理抢占策略伪码:if mem_pressure > 0.85 and req.len > long_thresh then swap_out_kv(req) and requeue(priority=low)。KV 分页复用:prefix_cache_hit if hash(system_prompt+template) in global_kv_pool then attach_shared_pages()。自适应并发控制:batch_cap = base_cap + k*(1 - mem_util) - m*queue_slope

四、效果数据

优化前后做了压测对照(脱敏示意,单卡同模型同数据集):首字延迟(P50)从约 3.2 秒降到约 1.4 秒,降幅约 56%;在并发 64 的场景下,有效吞吐(tokens/s)提升约 1.9 倍。GPU 利用率从"看着满实则空转"的约 70% 提升到稳定约 88%,排队超时率从约 9% 降到约 1.2%。显存碎片导致的 OOM 事件从每周数次降到接近零。代价是草稿模型多占了一点点算力,但相对主模型收益可以忽略——整体每 token 成本反而下降约 30%。

一个有意思的副作用:因为首字快了,业务方敢把模型接进实时对话场景了,之前因为慢被挡在门外的一些交互式用例,现在跑得很顺。

五、可复用经验总结

第一,吞吐优化先连续批再投机解码。顺序很重要——先把批调度做顺,投机解码的验证批才能高效地塞进去,反过来收益会打折扣。第二,KV 缓存复用决定了显存的实际上限。分页 + prefix 共享看着是工程细节,实则是长文本和高并发场景的生死线。第三,草稿模型要对齐主模型分布。投机解码不是随便挂个小模型就行,命中率上不去就是负优化,轻量微调的投入非常值得。第四,并发参数要自适应不要写死。业务流量是波动的,固定参数要么浪费要么雪崩,一个小控制器就能把稳定性拉回来。

给同行一句实话:自托管推理的性能问题,八成在调度不在模型。先把连续批、KV 复用、抢占恢复这三件套做扎实,再上投机解码这类锦上添花,顺序错了事倍功半。

结语

推理优化是门平衡术——延迟、吞吐、显存、成本四者互相牵制。我们这次最大的收获,不是某个参数调对了,而是建立了一套"剖析—定位—分层优化—压测验证"的闭环方法论。下次换模型换卡,这套打法照样能复用。