先把当时的情况摆出来。服务按请求量动态组批,20G 卡上平时 batch 8 稳跑,遇到同一秒涌入的长文本,批次组到 24 条、序列长度 4k,第三步直接 CUDA out of memory。
原因不止一个,得分开看。组批只看条数不看 token 总量,长序列把激活值推高。另一种情况是没有给 KV cache 的增长预留空间。
还有一种情况,OOM 后重试时上批张量还没释放。另外,缓存分配器碎片化,能分配的最大块变小。
组批上限改成按 token 总量算
python -c "print('max_tokens_per_batch=8192')"
随后扩批前先看剩余显存
python -c "import torch;print(torch.cuda.mem_get_info())"
OOM 时把批次减半再试
python -c "print('on OOM: batch//=2 retry')"
末了用长文本压测确认稳定
python loadtest.py --long-ratio 0.3 --duration 120
同样的操作我在测试机上先走了一遍,线上只做验证过的部分。
别只看报错消失,验证要多做一步。长文本压测 30 分钟内 OOM 计数为 0,批次 token 总量稳定在上限内,吞吐下降不超过 10%。
容易忽略的是,显存峰值由最长的那个 batch 决定,按平均值规划容量一定翻车,上限要按最坏情况定。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
