问题出现得很突然,日志倒是留得挺全。批量推理服务按固定 16 条组批,平时显存占用 40GB 左右。某天来了一批超长文档,单条 30 万字符,整批显存冲到 79GB 触发 CUDA out of memory,报 tried to allocate 2.4GB。把 batch 降到 8 之后仍会在那一条上炸,日志里能看到同批其他样本都很短。
刚开始盯着「padding 到批次内最长,短样本被一起拉长」,折腾了半个多小时,排掉了。
这类报错背后常见的原因有几处,逐个排除就行。组批按条数算,没有给 token 总数设上限。少数情况下是长样本的 attention 显存随长度平方增长。
另外,超长样本没有单独走切分或者流式路径。
第一件事是统计这批输入的 token 分布
python -c "import json;print(sorted(len(json.loads(l)['text']) for l in open('in.jsonl'))[-5:])"
随后改成按 token 预算组批
python -c "print('max_tokens_per_batch=8192')"
超长样本切块并留重叠再送
python -c "print('split long doc into 8k chunks with overlap')"
复现那条长请求确认不再 OOM
curl -s http://127.0.0.1:8001/generate -H 'Content-Type: application/json' -d '{"text":"...","max_new_tokens":128}'
改完先别撤,确认这几项。长文档那批请求正常返回,显存峰值稳定在 55GB 以下,整体吞吐只下降 6%。
容易忽略的是,按条数组批遇到长尾输入必然翻车,组批维度要换成 token,并且给单条输入设一个硬上限。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
