最近在做一个小项目,把微调过的Qwen2.5-7B接到公司内部知识库问答上。本地测试一切正常,但推到服务器上就出问题了——用的是A10(24G显存),模型加载完占18G左右,按理说还有富余。结果只要并发一上来(大概3-4个请求),直接就CUDA OOM。我用的vLLM,加了--max-model-len 4096,并发数设的8,但日志显示实际批处理好像没生效?另外默认的KV Cache是不是没自动调优?试过把--gpu-memory-utilization调到0.9,还是不行。有没有大佬遇到过类似情况,是量化精度选错了(目前用的AWQ),还是并发控制参数根本就没奏效?求指点,孩子快被线上事故逼疯了。
部署Qwen2.5-7B到生产环境,显存明明够却一直OOM?
全部回复
共 49 条vLLM的preemption和KV Cache默认策略在7B上容易踩坑,试试把max-num-seqs调小到2-4,另外别用AWQ换GPTQ可能更稳。
这情况大概率是max-num-seqs没限制住,并发8会炸显存,改成2试试,量化换GPTQ也行。
同款问题踩过坑,A10这卡跑7B量化看着余量够,但vLLM的KV cache默认策略很迷,加上你并发8个请求每个预留序列长度都会吃显存。建议先把max-num-seqs压到2-4试试,或者直接看下vllm serve启动时的真实内存分配日志,别光看nvidia-smi。另外AWQ在24G卡上其实没必要,用GPTQ或者干脆FP16加--enforce-eager关掉CUDA graph,显存能省出一大截,就是吞吐会稍微降点。
大概率是vLLM的KV Cache没按实际并发释放,试试--max-num-seqs压到4,或者开--enable-prefix-caching。
我之前调Qwen系列也踩过类似的坑,vLLM那个--max-model-len不是光设个上限就完事了,它会影响KV cache的预分配策略,你并发一上来每个请求都按4096长度去预留空间,24G看着够,实际一算就爆了。建议先查一下/proc/meminfo和nvidia-smi的实际峰值,别光看加载完的静态占用,批处理没生效很可能是--max-num-seqs没同步调,vLLM默认的调度窗口跟你想的不一样。AWQ这块我倒觉得不是主因,4bit量化省的是权重显存,但KV cache是实打实的fp16,你试试把--kv-cache-dtype改成fp8,或者干脆手动设--block-size 16,有时候默认的block太大反而容易碎片化。还有个骚操作,用--enable-prefix-caching,如果知识库问题有共同前缀,能显著降低重复计算,但得确认你的微调模型没改attention结构。最后实在不行,把并发降到4,然后开--swap-space让它溢到CPU内存,虽然慢点但至少不崩,生产环境稳定优先。
看到这个帖子我太有共鸣了,之前部署Qwen系列也踩过类似的坑。你提到并发一上来就OOM,但显存看着还有富余,这多半不是量化精度的问题,AWQ在7B上一般不会成为瓶颈。我怀疑是vLLM的--max-model-len和--gpu-memory-utilization这两个参数在打架,你设了4096但没调KV Cache的预留比例,vLLM默认会按比例预留显存给KV,如果并发请求的序列长度差异很大,实际峰值可能远超你预估的18G。建议你直接把--gpu-memory-utilization降到0.8试试,同时加个--enforce-eager关掉CUDA graph,虽然会慢一点但能显著降显存碎片。另外你说的批处理没生效,可以看下是不是--max-num-seqs没显式设置,vLLM有时候会默认用比较小的值,导致并发请求排队而不是真正batch。还有个偏方,把输入输出的长度限制再收紧点,比如max-model-len改2048,很多知识库问答其实用不到那么长上下文。最后实在不行就换GPTQ或者FP8试试,有时候AWQ的kernel在A10上反而比原生FP16更吃显存,别问我是怎么知道的。
试试把max-num-seqs调小到2,再配个--max-num-batched-tokens限制下,A10的带宽撑不住8并发。
你这KV cache估计被预分配占满了,加个--enable-chunked-prefill看看,能省不少显存。
这问题我上周刚踩过,vLLM的--gpu-memory-utilization只管显存分配上限,但KV cache是动态增长的,你并发一上来,老请求的KV还没释放,新请求就得挤内存,直接炸。建议把--max-num-seqs降到2试试,另外AWQ量化对7B来说收益不大,不如直接FP16配合--enforce-eager关掉CUDA graph,能省不少碎片显存。
试试把max-num-seqs调小到2-4,A10的带宽撑不住8并发,另外检查下prefill和decode的显存峰值分配。
这问题我踩过一模一样的坑,A10跑7B AWQ其实挺极限的,18G只是权重,KV cache和激活值才是大头。你试试把max-num-seqs从默认的256降下来,比如设成32,同时把--block-size设成16,vLLM的连续批处理对显存碎片特别敏感。另外gpu-memory-utilization调到0.9反而容易让KV cache预留不够,建议先降到0.85跑一下看日志里的KV cache比例。如果还不行,检查下是不是微调后模型结构变了导致prefill阶段临时显存峰值太高。
说实话我第一反应也是KV Cache没调好,但你gpu-memory-utilization都拉到0.9了还炸,那更像是max-num-seqs没控制住,vLLM默认会把并发请求全塞进一个batch,你设了8但实际峰值可能远超这个数。AWQ在7B上显存占用其实还好,不是主要瓶颈,建议先看下日志里实际batch size和sequence length是不是被拉满了,可以试着把max-num-seqs降到2或3,再把block size调小一点看看。另外你本地测试是不是没开并发?单请求跟多请求的显存峰值完全两码事,生产环境最好再留个2-3G缓冲。
vLLM的KV cache默认会吃满剩余显存,试试--max-num-seqs限制到2或4,另外AWQ配A10容易炸,换GPTQ或FP16稳点。
把max-num-seqs调低点试试,比如4,A10的显存带宽撑不住8并发的大batch。
也可能是AWQ的KV cache没走量化,换成FP8或GPTQ看看峰值显存变化。
这情况我也踩过坑,A10虽然24G但vLLM默认会预分配整块显存给KV cache,你那个--gpu-memory-utilization 0.9可能没生效,我猜是没配合--enforce-eager一起用。之前我跑7B也是并发一多就炸,后来发现是--max-num-seqs没设,vLLM会按模型最大长度算缓存,直接把剩余显存吃满。AWQ本身没问题,但建议你改成--kv-cache-dtype fp8试试,能省不少。另外确认下是不是有个别请求带超长上下文,单条就把预留空间打穿了,最好在代码里卡一下输入长度。
vLLM的批处理没生效大概率是max-num-seqs没放开,默认只有256,但你这8并发不至于撞墙,真正的问题可能是KV Cache的预留策略太保守,0.9利用率也没覆盖到中间层。我上次跑7B也这样,后来把--max-num-batched-tokens调高到8192,同时显存利用率改0.95才稳下来。另外AWQ在低并发下没问题,但一旦batch变大,反量化会吃点显存,你检查下是不是paged attention的block大小没配好。
看到这个帖子简直像看到上周的自己,我是在4090上部署Qwen2.5-7B做RAG,也是本地好好的上服务器就炸。你这个问题大概率不是显存总量不够,而是vLLM的预分配策略和你的并发设置打架了。--gpu-memory-utilization 0.9是告诉vLLM可以吃掉90%显存,但如果你没显式设置--max-num-batched-tokens或者--max-num-seqs,它可能还是按保守的KV Cache预留来算,导致实际批处理窗口很小,并发一上来就得临时扩容KV,直接挤爆。建议你先把--gpu-memory-utilization降回0.85,然后强制加上--max-num-seqs 4试试,同时看一眼--block-size是不是默认的16,A10上经常要调成32才能减少碎片。另外AWQ对7B其实收益不大,你试试FP16或者GPTQ,有时候反而因为量化反量化多耗显存。还有个小坑,你微调后如果没重新跑vllm serve的校准,它可能还按原模型的层数分配KV,这个很容易忽略。最后实在不行,把--enable-prefix-caching打开,知识库问答的重复前缀能省不少显存,我开了之后并发翻倍都没再OOM。
看到你这个情况我第一反应是vLLM的KV Cache策略可能跟你预想的不太一样,它默认会按照--max-model-len和--gpu-memory-utilization来预留空间,但实际批处理大小可能受限于每个请求的序列长度,如果输入输出token数波动大,3-4个并发就把预分配吃满了。我之前遇到过类似问题,后来发现是--max-num-seqs没设,默认值可能很低,导致并发请求没真正进同一个batch,你可以查一下这个参数。另外AWQ量化虽然省显存,但反卷积和Gemm的临时缓冲区有时会突然暴涨,尤其长文本场景,建议试一下把--block-size调小到16或8,能缓解碎片化。还有个排查方向,看下是不是微调时padding策略导致模型实际最大长度远超4096,vLLM会按实际长度分配,但日志里不一定显眼。最后狠一点的办法,直接开--enforce-eager关掉CUDA graph,虽然慢点但OOM概率会降很多,先保线上稳定再优化。
看到你说vLLM批处理没生效,我第一反应是max-num-seqs没跟着调,这参数默认才256,但你并发8的话理论上不会卡这里。真正可疑的是KV cache的预留空间,你设了gpu-memory-utilization 0.9,但vLLM还会额外留一点给torch的context,实际上可用内存比你想的少,尤其A10的带宽跑7B AWQ本来就吃紧。我建议你先把max-num-seqs降到4试试,然后看下vllm的日志里实际KV cache的block数是多少,如果只有几百个block那肯定一并发就爆。另外你确定微调后的模型权重是完整的FP16吗?我之前遇到过合并LoRA后推理时临时把权重复制了一份,显存瞬间翻倍的情况。还有就是vLLM的版本,0.4.x和0.5.x对preemption的处理差很多,老版本遇到长请求会直接申请新block而不是复用,建议升到最新版。最后可以开一下--enable-chunked-prefill,虽然牺牲点吞吐但能救急,实测7B模型在4并发下能稳定不少。
看到这个我真是感同身受,上周刚在A100上踩过类似的坑。你光调gpu-memory-utilization没用,重点得看vLLM的日志里有没有报“Maximum concurrency reached”或者“KV cache blocks”相关提示,很多时候是max-num-seqs没跟着并发数一起改,默认值才256,你并发设8但批处理上限被卡死了。另外AWQ量化在7B上确实容易出幺蛾子,我之前用GPTQ就没这问题,但更关键的是你检查过--max-model-len和实际输入长度的关系吗?如果知识库的检索结果拼上历史对话后超过了4096,vLLM会强制重新计算KV cache,那显存直接翻倍。还有个隐藏坑——A10的24G在vLLM里实际可用只有22G左右,因为驱动和CUDA context要占掉2G,你加载完剩6G看着够,但每个请求的临时激活值加上KV cache增量,3-4个并发直接爆。建议先跑个单请求测试,用nvidia-smi盯显存曲线,确认是不是KV cache分配策略问题,实在不行就把--swap-space调大点试试,让部分KV cache落到CPU内存。
之前跑7B也踩过这个坑,排查下来多半是vLLM的KV Cache没按并发数动态分配,24G看着够但推理峰值会暴涨。建议先看下/tmp里有没有核心转储,然后把--max-num-seqs显式设成4,同时把--block-size调小到16试试。另外AWQ量化对7B来说收益不大,换GPTQ或直接用BF16可能更稳,毕竟A10的显存带宽扛得住。还有个土办法,把--enforce-eager加上关掉CUDA graph,能省点显存,代价是吞吐略降。
同款A10踩过坑,你那个18G是模型权重,KV cache峰值才是大头,4096长度下8并发很容易爆。试试把--max-num-seqs降到2或者3,然后把--gpu-memory-utilization改成0.85,留点余量给碎片。另外AWQ在7B上收益不大,换GPTQ或者直接用FP16说不定更稳。