首页 > IT职业 > IT生活 > 今天敲代码貌似特别顺利喵
写在前面:今天一整天在调vLLM前缀缓存prefill‑decode解耦的改造,难得没有连环踩坑,不过顺风顺水之下,反而发现几个平时被我们选择性忽略的工程坑点,聊点实操层面的东西。
不知道各位做推理基建的有没有这种体验,大部分工作日都是跟各种毛刺死磕。前几周我还在跟P99延迟抖动死磕:监控面板GPU利用率看着四平八稳,nvidia‑smi扫一圈也没OOM告警,但时不时就冒出来一波长尾延迟,偶发问题最难搞,属于那种复现看人品的玄学bug,抓现场全靠碰运气。
今天迭代prefill与decode流量隔离逻辑,初衷就是把计算密集型的prefill任务,跟HBM带宽约束的decode任务做资源切分。很多人看文档以为开个参数就完事,直接把prefill、decode混跑在同一组GPU池子里,短压测看着指标很漂亮,一上混合真实流量就翻车。
简单说下现象:大批量长上下文请求杀进来的时候,prefill会疯狂抢占Tensor Core资源,把正在跑decode的请求给挤到一边。decode阶段本身是 memory‑bound,不靠算力吃饭,吃的是HBM带宽,一旦被抢占,token生成间隔jitter直接起飞,TTFT看着还行,中间输出断断续续,业务侧就会看到流式输出一顿一顿。
一开始我的思路是做简单队列隔离,把两类请求丢进不同队列,以为队列分层就能万事大吉。跑第一轮压测才发现光应用层队列远远不够。k8s调度层面没有做硬件资源的染色,pod调度的时候还是会把两类负载调度到同一张卡上,队列分开了,GPU硬件层面还在抢资源,等于做了个无效的上层壳子,典型的 逻辑隔离不等于硬件隔离。
然后开始改调度侧逻辑,给prefill负载打上污点taint,专门分出一部分GPU节点池只处理prefill;剩下节点专门承接decode生成。改造完第一轮压测,指标肉眼可见变好,但新问题又来了。prefill节点池会出现潮汐式的资源浪费:低谷的时候prefill任务寥寥无几,这一批GPU就空转;流量洪峰过来,prefill又瞬间打满,出现队列堆积。
这里就遇到一个现实权衡:完全静态拆分节点池,隔离效果拉满,但资源利用率直接挨打;完全混布,利用率好看,长尾延迟SLO就悬在刀尖上。行业里面现在两种路线,一部分团队直接硬隔离,牺牲一点GPU利用率换稳定性;另一套方案做动态卸载,空闲时把prefill节点接纳少量decode流量,高峰期再做驱逐。但驱逐逻辑又会带来新麻烦,正在执行中的请求不能随便kill,只能等本轮请求跑完再回收资源,驱逐窗口期控制不好,会出现请求悬停。
还有个顺带的坑,就是 prefix caching复用逻辑。很多人迷信前缀缓存可以无限降prefill开销,就无脑开大缓存块。现实多租户场景下,跨租户KV块复用是高危操作,如果没有cache_salt隔离,存在块哈希碰撞带来的上下文串味风险。不要迷信论文里的命中率数据,论文大多是干净数据集,线上流量五花八门,prompt前缀重复率远没有实验室那么好看,一味放大缓存池,只会持续膨胀显存占用,拉高OOM概率。
今天整套逻辑调完,压测反复跑了好几轮,P99延迟降下来,GPU利用率也控制在可接受区间,没有出现极端空转。敲代码的时候一路下来没有那种改一行出一个报错的地狱循环,才会有标题这种“敲代码特别顺利”的错觉。
不过做推理基建久了,心里很清楚,现在的状态只是压测环境下的暂时稳态。一旦丢进真实线上,用户流量模型一变,新的边角case大概率还会冒出来。现在日志、metrics、trace链路已经备好,就等明天上预发布环境遛一圈看看实际表现。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048457/viewspace-3184808/ ,如需转载,请注明出处,否则将追究法律责任。