优先级反转在操作系统课里是个经典三段式:高优先级任务 A 等着低优先级任务 C 手里的锁,中优先级任务 B 趁机抢了 CPU,结果是 B 跑完了 A 还卡着。教科书给的解法也经典:优先级继承、优先级天花板、关中断。但在推理服务的调度器里,这套东西直接搬过来会撞墙,因为“谁在持有资源”这件事在这里变得模糊。
把三类东西映射一下:高优先级请求是按 SLA 承诺要低延迟返回的线上请求;低优先级请求是挂着批量任务或评估流量的请求;中优先级是排队里那些优先级居中、但提交频繁的常规请求。问题常出现在 KV Cache 和批处理槽位被当作共享资源的时候。
反转是怎么发生的
先问:谁占着资源?是显存里那块 prefill 到一半的长 prompt 的 KV 块。低优先级的批量请求塞进来一个两万 token 的长文档,prefill 占满了一大块显存,这时高优先级请求到达,进了准入队列。它不会被阻塞在“锁”上,而是被卡在排不进批上——调度器发现剩余 KV 空间不够下面连续 decode 需要的 block 数,连续几轮迭代都没把它拼进 batch。
与此同时,中优先级请求不断进来。如果调度的分配口径是严格的剩余 slot 优先,只看当前这一轮哪个 batch 能填满,这时中优先级请求体短、好拼,就被接纳了。高优先级请求虽然优先级高,但它在这一轮所需的空间没有人腾出来,反而是持续进站的中优先级请求把每个 batch 都占了。
这个过程中,高优先级请求被“延迟执行”,但它没报警——只是 P99 在攀。等到长 prompt decode 结束、KV 释放,它才被接纳。对应来看,操作系统里 B 先执行完,A 才拿回资源;推理服务里中优先级请求一直占着 batch 槽,直到低优先级请求自己自然收尾。
为什么优先级继承不好用
优先级继承的核心是低优先级的持锁方继承等待方的高优先级,从而不被中优先级抢占。推理服务能做类似的事:如果一个高优先级请求在等某个长请求释放 KV,就把这个长请求临时提权。但有个硬伤:低优先级长请求一次 prefill 占 2 万 token,可能再跑半分钟;把它提到最高优先级意味着“排在它后面的所有 request 都等它这一大段”。短期内腾不出空间,只是把等待换成了更慢的排队。
另一个问题是持有者的判定。推理一次的 KV 占用是逐步增长的,并非给锁付定金。一个请求在第 50 个 token 的时候锁定了前缀缓存(prefix cache)的某一页,第 300 个 token 时又释放了一部;持有者判定要随每一步每页随动,标准继承机制没法在这种粒度上接力。
现实一点的做法
更实用的路线是绕开“创建时继承”的限制,把它改造成准入时的账本控制。具体有三件事可以做。
- 把 max_num_batched_tokens 按优先级动态切片。每轮迭代之前,预留一块“高优先级 rescue buffer”,只允许 P0 请求使用。这块尺寸等于从单条请求的 KV 增长速率反推的值,比如 decode 阶段每条每次一步吃掉几十个 token case,按保守估计数留几十条 request 的量。P1 请求用剩余的 part。效果是高优先级即使排队,也不必和中优先级抢同一个剩余额度池子。
- 给低优先级单请求设 KV 预算上限。一个 2 万 token 的批量 request 预分配 KV,实际是在无任期地长期把资源揽住。把 max_model_len 对某优先级限制变小,逼它拆块提交,或者至少限制并发存活的长请求数量。这样它在高峰期不贡献排他的 KV 回填,只占各批自己承诺那份。
- 把等待信息放进观测。当 P0 请求排队超过阈值,必须在 next-token latency 打上标注同时标 scheduler 未提交、申请了多大 KV 申请、还要多久才被满足。只看看板计数会把“排队时间”掩盖在每个 gate 后面,因为它根本不存在 queue length 里。
取舍与代价
预留容量意味着计算率降,任何剩余空闲 slot 都在跑。batch大小降低到 87% 和降低到 92% 的时候,吞吐差别近乎可见;预留太大的话,晚高峰的排队更长。不过这项损失比把 SLA 打成 P99 飙升要便宜,如果能兑现合同,就值。
KV 预算对批量任务施加时也会反噬:本来能像长文本摘要那样一次处理进的批量输入,被切成多块会让端到端统计不可比、重现任务周期感更笨。这是要分摊的代价,不要认为没有缺点。
把操作系统里“高优先级等待资源”翻译成推理服务里“高优先级等待调度可容纳空间”,继承就变成动态预留。我们继承了半天,最后绕回到 budget,其实也符合调度器不是多线程 Runtime 的性质。
什么时候根本不该区分优先级
如果用户没有隔离预算,全部单模型一律走同一个请求队列,高优先请求实际上常常只是一种“前台页面、用户正注视”的样本,排队长度无法精确分摊,优先只代表排序占位而没有等待重定点。在推理长 prefill 恰是当前正在用所有 GPU 最大能力处理对象的时候,任何时间片保护反而是干扰。实际中选择较少,常规思路是靠多等级租队列、物理分隔资源——在前一篇文章所述推理服务多租户配额的一层,把 P0/P1 分配到不同副本上去,而非默认共享调度层。优先级反转也就没有栖身之所了。
转载请注明出处: 皮哈皮阿
本文的链接地址: https://blog.phpat.com/ai-frontier/651.html
微信或手机浏览器扫一扫,随时随地随心阅读与分享
-
多智能体不是银弹:编排、通信与成本取舍
我们试过让五个 Agent 开会,结果它们花了二十分钟争论谁该先说话,最后交上来的方案还不如一个单 Agent 加两个工具。多智能体不是不能做,是很多团队做早了。
2026/10/18
-
AI 浏览器用了一个月,我还是回到了地址栏
我试着把 AI 浏览器当主力用了一个月。模型不差,功能也不少,但最后让我放弃的是一件很朴素的事:地址栏比对话框更快、更确定。AI 浏览器到底卡在哪?
2026/10/20
-
个人 Agent 与常驻智能体:长期记忆、主动性与隐私边界
我让一个常驻 Agent 帮我盯快递。包裹签收三天后,它还在提醒我“预计今天送达”。长期记忆、主动性和隐私边界,决定了个人 Agent 是助手还是负担。
2026/10/20
-
世界模型被吹了两年,真正难的不是生成视频
看世界模型的演示视频,很容易产生“就差一点”的错觉。可一旦你试图在里面做一个动作,问题就全暴露了。生成一段像世界的视频,和拥有一个能交互的世界,是两件难度完全不同的事。
2026/10/20
-
思维链压缩到 20%,还能保住数学推理的准确率吗
把推理模型的思维链砍到原来的 20%,多数压缩方法会崩,但 Extra-CoT 在 MATH-500 上还保住了近半准确率。拆一下它怎么用公式原子性和分层奖励,以及这些结果在别的任务上不一定成立。
2026/10/22
-
前缀缓存命中率:字节对齐与工程取舍
从 QwenPaw 的命中率议题、Reasonix 的前缀分区,到 vLLM 的缓存感知路由,拆开前缀缓存失效的真实触发器,并讨论冻结前缀之后要执行换来的工程代价。
2026/10/24
京公网安备11011402053654 
@muffin:链接已更新,分类图像功能...
AI网址导航模版图标库更换指南
作者大大,图标库邀请链接失效了,麻烦更新...
AI网址导航模版图标库更换指南
太好看了,快点更新!
友情链接
@戴墨镜的刘备:哈喽,路过点赞。
vue.js组件之手写签名板vue-signature-simple
太好看了,快点更新!太棒了!👍真的很赞!
vue.js组件之手写签名板vue-signature-simple
你写得非常清晰明了,让我很容易理解你的观...
Emlog插件RSS订阅器发布