多租户推理服务里有个问题会反复出现:某个租户的长上下文请求把显存吃满后,被人为限制或租约到期,你要把它的 KV Cache 收回。手上的工具有 free、clear、pin、compress 这些接口,真正痛的地方在于:块是散落在各个 block table 里的,究竟回收多大一块显存、回收之后那些还活着的请求靠什么继续解码,这两件事必须在同一个动作里想清楚。
先搞清楚一个租户到底占了多少显存
按 Qwen2.5-7B 来算,28 层,H_kv=4,head_dim 128,FP16,每个 token 的 KV 大约是 56 KB。batch=32、序列长度 32768 时,总缓存接近 57 GB,是模型权重 14 GB 的四倍。换成 72B 的模型,每个 token 跳到 320 KB,32K 上下文下每并发送四路就吃掉 160 GB。租户维度的账本要在这个量级上记,不能只看请求数。
常见的拆分是:一个租户的配额按“块 + token”双重计量。块决定碎片率上限,token 决定真实使用量。PagedAttention 把碎片率压到 4% 以下之后,这里的失配已经小了很多,所以块这块可以少记一点,直接在 token 侧做硬上限更省事。但要注意共享前缀:同一个租户的多个会话如果共用系统提示,前缀那部分块是引用计数共享的,退租时不能按块的数量直接减,必须递归释放引用,否则下次命中前缀会踩到已释放的物理地址。
回收的四种手段,代价不一样
| 手段 | 适用场景 | 副作用 |
|---|---|---|
| 直接释放至空闲池 | 请求已经结束 | 零成本,是最干净的一条路 |
| 卸载到 CPU DRAM | 多轮对话空闲等待 | 预取回来要交一笔延迟税,并且会争抢 host 带宽 |
| 压缩 | 冷 token,注意力权重低 | 属于有损操作,回滚不了,精度影响要分别评测 |
| 驱逐 | 超长上下文的后半段 | 上下文断裂,会让模型表现出现回头重问 |
这四条里,只有第一条没有损失。看 LMCache 对外开放的接口清单也能发现这个倾向:clear(tokens, instance, location)、pin()、compress() 排在最前面,淘汰逻辑要写在调用方的策略里。工程化上我建议按分层顺序来做:先清空不再活跃租户的冷块,再把挂起会话卸载到 DRAM,只有当 DRAM 水位报警的时候,才进入压缩环节;驱逐放到兜底位置,不要一开始就打开,因为压测时带来的延迟抖动特别难拉回来。
一个高频踩坑是长期驻留的缓存块。系统提示这类内容被 pin 在 GPU 上,配额算的是实际使用量,如果把它算成“可回收”,退租时肯定收不回预期的那部分显存,账本便会和实际水位长期不吻合。
被回收的请求哪里都不能去
配额回收的一大难点是:被减配的租户还有在跑的 decode。此时有两个选择。选择一是让它们进入排队,这就是抢占的路线。选择二是允许上下文继续增长,拒绝新请求。经验上从第一批被抢占的请求就要考虑可观测,这部分确实不轻松:已经生成了一半的内容都还没有返回,重新进队列又要 OOM,保留原状又会挤压别的租户。
抢占比回收更容易做对,因为被抢占的请求状态可以存档重放,代价只是首 token 重新计算 Prefill。反而更难做对的是碎片:回收按 token 计算和按块计算容易出现不一致,久了会出现那种“账面上空闲块还有,但实际上请求连续进来注册也找不到地方挂”的窘境。GPU 显存碎片率正好列出了这个场景。判断基准也很清楚:如果一块配额被归还后 allocator 无法立刻被 top-up 请求使用,就意味着分配器需要 rebalance,这部分逻辑目前还没实现。
另一个容易被忽略的隐藏账单(经常被视为细枝末节的事务):其他租户共享前缀。如果回收走到物理层回收这一步,可能会连带命中其他租户用同一系统提示产生的缓存,只能按 token 逐级扫描,找不到就停手。
配额要和分页表绑定,不要再把计费模型挂在序列上
把配额从历史上只负责请求次数改为按字节管理。每个租户实现一个独立的 block table,按块给物理页建档,配额释放要求遍历 block table;这里唯一正确的粒度是单块释放,而不是按租户批量清扫。如果图省事反而更麻烦的地方在于和前缀缓存和分块的配置不相对应,一旦并发上来后,首 token 阶段的预计算会撞上墓碑页并且访问导致读取
转载请注明出处: 皮哈皮阿
本文的链接地址: https://blog.phpat.com/ai-engineering/654.html
微信或手机浏览器扫一扫,随时随地随心阅读与分享
-
推理成本下降之后:模型路由、KV Cache 与端侧推理
上个月一个团队拿着账单来找我:模型单价降了,费用却涨了三倍。看完调用链就明白了,问题不在单价,在用法。单位 token 便宜,不等于每次任务便宜。
2026/10/10
-
2026 年 AI 应用评测:从单轮打分到多轮轨迹评估
一个 Agent 的评测分数从 72% 涨到 81%,团队很高兴,直到发现它学会了在失败时直接结束任务,把“没做完”算成了“无需回答”。评测设计错了,指标越好看越危险。
2026/10/19
-
推理模型的流式输出:thinking 块怎么流
推理模型的流式输出不只是逐字渲染:思考块、正文、工具调用参数混杂在 SSE 流里,客户端要按字段分流、独立缓冲、支持中途中断。记录接通义千问与智谱过程中的判断和踩坑。
2026/10/24
-
长度惩罚参数调优:常见参数名字容易混淆
长度惩罚在主流 API 里并不存在。真正管长度的是 max_tokens 和 stop sequences,frequency、presence、repetition 惩罚管的是用词重复和新词探索。把这些旋钮分开,能避免输出被截断、术语被替换成同义词两类故障。
2026/10/23
-
动态拼批不是开个开关:线上拼批的取舍与门禁
在线服务里的动态拼批和离线批量推理是两码事。窗口时长、KV Cache 水位、批内参数对齐共同决定拼接能否成立。上线前该盯的是 p99 和显存峰值,而不只是吞吐。
2026/10/25
-
推理服务排队延迟的分层观测:从请求数到Token账本
盯 QPS 和 P99 看不到排队延迟长在哪。把这件事拆成入口→上游准入队列→后端等待→batch 解码四层,用 vLLM 暴露的排队与 KV 缓存指标做层级归因,讨论分层之后仍然看不见的部分与取舍。
2026/10/27
京公网安备11011402053654 
@muffin:链接已更新,分类图像功能...
AI网址导航模版图标库更换指南
作者大大,图标库邀请链接失效了,麻烦更新...
AI网址导航模版图标库更换指南
太好看了,快点更新!
友情链接
@戴墨镜的刘备:哈喽,路过点赞。
vue.js组件之手写签名板vue-signature-simple
太好看了,快点更新!太棒了!👍真的很赞!
vue.js组件之手写签名板vue-signature-simple
你写得非常清晰明了,让我很容易理解你的观...
Emlog插件RSS订阅器发布