那天晚上,我对着仪表盘上那条红色OOM标记皱起眉头。我的单张RTX 3090上,WhisperX large-v3和Ollama devstral-small-2(一个24B的Q4_K_M量化模型)已经跑了几个月,但每次我对着语音助手说话、恰好赶上邮件自动分类任务运行时,显存就会崩塌。nvidia-smi只能看瞬时值,抓不住两个服务重叠的毫秒级尖峰。我需要每个服务的VRAM历史,于是我打开了自己搭的homelab-monitor,切到“AI Models”视图,把时间轴拖到重叠窗口。
画面很直接:两条曲线在几分钟内同时爬升,合力顶穿了24GB的天花板。这条天花板线是我们画的——就在仪表盘的GPU视图里,用容器一键部署,配合NVIDIA Container Toolkit把每个模型服务器的显存都扒出来,远程节点走SSH就能监看。而这时候我才意识到,问题的根源不是WhisperX那点推理开销,而是邮件分类模型预留了太多几乎用不到的KV缓存。
固定开销是模型权重。Devstral 24B在Q4_K_M下吃掉大约15GB,WhisperX large-v3占掉其余的一部分,留给动态扩展的空间本就紧张。可变的部分是KV缓存,它与上下文长度num_ctx成线性关系。我从Langfuse里拉出邮件分类管线的请求记录,发现真实输入的token数从来没有超过5~8k,可模型却是按40k窗口加载的,相当于有大约32k token的KV缓存被白白预留,什么正事也没干。
这就变成了一个简单算术题:到底需要给邮件分类留多少上下文?既然是Mistral 3架构,我直接通过Ollama的API拉出了模型信息:总共40层,KV注意力头数为8,每个头的键向量长度128,值向量长度也是128。按FP16算,每token的KV缓存就是2(K+V)×40层×8个头×128维×2字节,等于163840字节,约0.156 MB。所以如果把上下文窗口压回原生长度8192 token,缓存开销不过1.28 GB;而之前40k窗口对应的缓存将近6.4 GB,两个服务一叠加就爆炸。
8192这个数字正好卡在邮件分类真实需求的上方,又不会浪费。我在Modelfile里把num_ctx改成8192,重新部署后拉长时间观察,仪表盘上那条OOM标记再没出现过。WhisperX和邮件分类相安无事,整个fix只动了一个参数。整个过程的测量方法、计算公式和Ollama的模型信息提取命令我都整理成了可复现的方案,你在自己homelab上照着敲就能验证——克隆仪表盘仓库、启动Docker Compose,剩下的就是盯着曲线,把多余的上下文一口口咬掉。
热门跟贴