最近在做一个小项目,把微调过的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机制在捣鬼,A10的24G跑7B AWQ按理说余量挺大的。你加了max-model-len但没动KV Cache的预留策略,vLLM默认会按gpu-memory-utilization的90%去预分配KV cache,但你这18G是模型权重+激活,实际给cache的余量可能只剩2-3G,并发一上来cache不够就直接OOM,日志里可能还有“GPU cache insufficient”的警告你没注意。建议先查一下启动日志里实际分配的KV cache block数量,如果远小于你预期,试着把--max-num-seqs调低到2-3,或者直接设--block-size 16看看,有时候A10的显存带宽小,block太大反而碎片化严重。另外你提到AWQ,如果用的是GPTQ量化版本,建议换回FP16对比一下,有些微调模型在AWQ下数值分布异常会导致KV cache占用暴涨,我之前碰到过类似问题,最后发现是量化层和vLLM的融合算子不兼容。还有个细节,公司内网知识库的prompt可能很长,你虽然设了4096,但如果实际输入经常顶满,那每个请求的KV cache峰值会很高,并发3个就崩很正常。试试开--enable-prefix-caching,如果知识库问题有公共前缀,能省不少cache空间。最后别急着改并发,先用单请求压测看显存曲线,确认是cache分配问题还是激活内存峰值,A10这种卡真的得精打细算。
试试把max-num-seqs调小到2-3,A10的显存带宽撑不起8并发,另外KV cache开paged attention了吗?
会不会是vLLM的KV Cache没跟着并发走,试试设--max-num-seqs再调低点,另外AWQ对7B提升有限,换GPTQ或者FP16看看呢?
你这情况八成不是显存总量的问题,是vLLM的KV cache和prefill并发挤在一起了。A10带宽本来就一般,3-4个请求同时进来,每个都要分配完整的KV cache块,18G模型+预留的cache很容易就爆了。试试把--max-num-seqs调小到2或者3,再配合--max-model-len砍到2048看看,另外AWQ在低并发下收益不大,可以先换回FP16排除量化问题。之前我碰到类似情况,调完--block-size到16也能缓解不少。
vLLM的KV cache默认会吃掉剩余显存,3-4并发就爆很可能是max-num-seqs和KV cache策略没配好,试试调小点。
之前我也踩过这坑,AWQ没问题,重点看下--max-num-seqs是不是默认值太大,手动改成2或4再测下。
试试把max-num-seqs调小到2-4,A10上并发8太激进了,KV cache碎片化才是元凶。
这个现象挺典型的,A10跑7B AWQ按理说余量很足,但你检查下vLLM的--max-num-batched-tokens是不是默认设太小了,并发上来时单序列长度没超但总token数爆了。另外KV cache的显存分配是按峰值预留的,你手动调0.9反而可能挤压了模型权重和激活的空间。我之前遇到过类似情况,最后是把--max-num-seqs降到4,同时把--block-size改成16才稳住,你可以试试看是不是预填充阶段吃满了显存。
碰到过类似的坑,说个方向你试试看——vLLM的KV Cache其实不只看--gpu-memory-utilization,还得结合--max-num-seqs和--max-num-batched-tokens一起调,默认值在A10上可能偏激进。你设了并发8,但3-4个请求就炸,很可能是每个请求的序列长度波动大,导致KV Cache预分配炸了,尤其是AWQ虽然省了权重显存,但激活和KV Cache反而更吃紧。另一个疑点是你微调过的模型,如果加了LoRA或者改了attention实现,vLLM的PagedAttention可能没完全兼容,批处理失效时日志会显示num_sequences异常,你可以开--verbose拉一下实际调度曲线。还有,别完全信nvidia-smi的占用,CUDA context和PyTorch缓存会预留空间,建议把--swap-space设成0,强制走显存。最粗暴的办法是先降--max-model-len到2048测并发,如果稳了,那就是前缀缓存或长尾请求的问题,再针对性开--enable-prefix-caching。最后确认下A10的驱动和CUDA版本,vLLM有些版本对Ampere架构的KV Cache优化有bug,升级到最新版或换个0.6.x分支可能直接解决。
试试把max-num-seqs调小到2-3,vLLM默认批处理会疯狂占KVCache,你这并发8纯属给自己挖坑。
看到这个情况我第一反应是vLLM的KV cache会按max_model_len预分配,你设了4096但实际输入长度可能没到,空闲显存会被预留给后续token,并发一多反而容易炸。建议先把max_num_seqs调小到2试试,另外AWQ对7B模型收益不大,直接FP16可能更稳。还有你那个--gpu-memory-utilization 0.9是不是没生效?可以看下启动日志里实际显存分配。
看到你这个情况我第一反应是vLLM的--max-model-len和实际KV Cache预留没对上,18G是权重占用,但KV Cache是按最大序列长度和batch size动态分配的,你并发一上来每个请求都往4096长度上靠,缓存直接爆掉很正常。我之前部署13B模型也遇到过类似问题,后来发现是--gpu-memory-utilization设置太高反而让vLLM预分配了太多显存给缓存池,导致剩余空间不足以处理突发请求,建议你试试把它降到0.85甚至0.8,同时用--max-num-seqs限制实际batch大小,别依赖并发数这个参数。
另外AWQ量化本身会略微增加解码时的临时显存占用,如果微调后模型分布有偏移,量化误差也可能让某些层激活值变大,你可以先切回FP16在低并发下跑一下对比看看。还有个容易被忽略的点——你本地测试是不是用单卡小batch,而服务器上vLLM的--max-parallel-loading-workers或者--tensor-parallel-size设置不对,导致GPU内存碎片化?建议看下启动日志里GPU memory usage breakdown那一段,确认KV Cache池实际分配了多少,另外检查下是不是有老请求的上下文没被释放,vLLM有时候需要设置--block-size为128才能更好管理缓存块。
之前跑Qwen2.5-7B也踩过类似的坑,A10那24G其实挺尴尬的,18G加载完看着余量不小,但vLLM的KV cache是按最大并发和max-model-len预分配的,你设了4096长度加8并发,默认它会按最坏情况去算,实际峰值可能远超你预期。--gpu-memory-utilization 0.9这个参数我试过,它更像是“上限”而非“启动时强制占用”,如果请求不够密集,它不会主动把没用的显存拿来扩cache,所以该炸还是炸。建议你把--max-num-seqs手动降到4试试,同时看一下/proc/meminfo确认是不是有别的进程占着显存,比如别的服务或者残留的Python进程。AWQ本身没问题,7B在A10上用4bit完全合理,但你要是用了--quantization awq而模型文件是GPTQ,那vLLM会偷偷跑反量化,显存直接翻倍。另外,日志里如果出现Number of blocks相关的warning,那就说明KV cache分配策略没生效,可以试试加--enable-prefix-caching或者把--block-size调成16,这俩对批处理影响挺大的。最后说个玄学,vLLM版本太旧的话调度器有bug,换个0.6.x以上的版本有时直接就解决了。
之前跑7B也踩过这个坑,A10上18G加载完其实剩不了多少,vLLM的KV cache会直接吃掉剩余显存,你设0.9反而可能把预留给CUDA context的空间挤没了。建议先把--max-num-seqs压到2试试,同时开--enable-chunked-prefill,另外AWQ在低并发下确实省显存,但并发一高反而容易爆,换GPTQ或者直接把--kv-cache-dtype改成fp8能缓解不少。还有个细节,微调过的模型tokenizer可能和vLLM的默认配置不匹配,导致序列长度计算异常,可以看下日志里实际prefill长度是不是远超4096。
看着像vLLM的preemption没生效,试试把--max-num-seqs调成2-4,另外AWQ对7B收益不大,换GPTQ或直接FP16测下。
之前跑QWen2.5的时候也踩过这个坑,vLLM的KV Cache默认是按模型最大长度算的,你--max-model-len设了4096但没调KV cache比例,实际预留空间还是按满算的,所以并发一挤就爆。建议先把--kv-cache-dtype切成fp8试试,能省不少显存,另外--max-num-seqs别设8,改成2或3看下还OOM不,这参数有时候比gpu-memory-utilization更直接。AWQ这块我倒是没觉得有问题,你确认下是不是微调后的模型weight跟量化配置不匹配,偶尔会有这种隐藏坑。
我之前也踩过类似的坑,vLLM的批处理没生效多半不是并发数的问题,而是max-num-seqs没跟着调,默认值可能比你想的低不少。你试下把--max-num-seqs设成4或8,同时把--max-model-len降到2048看看,A10上KV Cache留太少确实容易假性OOM。另外AWQ在7B上省显存有限,如果微调后分布偏移大,量化误差反而会让显存碎片化更严重,可以换GPTQ或者直接FP16对比一下。还有个隐蔽点,检查下是不是prompt里带了超长历史上下文,4096的窗口被单个请求占满,并发时直接爆。
这问题我上周刚踩过一模一样的坑,A10上跑7B AWQ其实挺极限的。你那个18G可能是权重+激活值,但vLLM默认会预留一部分显存给KV cache,并发一上来如果max_num_seqs没跟着调,老请求没结束新请求就挤爆了。建议先把--max-num-seqs压到4试试,另外--gpu-memory-utilization别拉到0.9,0.85左右给CUDA留点余量反而更稳。还有个细节,微调过的模型如果加了特殊token,--max-model-len实际会比你设的更占显存,可以看下/tmp里vLLM的日志确认下实际KV cache分配了多少。
看到你这个情况,我第一反应是KV Cache的pre-allocated空间可能没按你设想的来。vLLM虽然默认会按gpu-memory-utilization动态分配,但如果你用了--max-model-len 4096,它实际预留的KV cache大小是按最大序列长度算的,不是按实际请求长度。你18G是模型权重+激活,但KV cache在并发3-4个请求时可能瞬间涨到4-5个G,加上A10的24G还要留点给CUDA context,其实余量没你想象那么大。
另外AWQ量化在7B上通常能省30%-40%显存,但如果你微调时没做量化感知训练,激活值分布可能和原始模型差异大,导致KV cache存储精度反而需要更多空间。我建议你先把--gpu-memory-utilization降到0.85,然后加--kv-cache-dtype fp8试试——如果硬件支持的话,这能直接砍半KV cache占用。还有一个坑是vLLM的--max-num-seqs参数,你设了8但不一定生效,因为vLLM新版改叫--max-num-batched-tokens,这俩要一起调,否则批处理逻辑可能还是按默认16个序列来算,显存分配就炸了。
我之前跑7B也遇到过类似,最后是用--enable-prefix-caching配合--max-num-batched-tokens 2048解决的,把单批token数压小,让调度更保守。你检查下vLLM版本,老版本对A10的memory pool管理有bug,升级到0.6.3+试试。如果还不行,就换GPTQ的4bit,AWQ在长上下文下确实容易溢出。另外,你服务器上是不是有其他进程占显存啊?nvidia-smi看一眼是不是有其他残留,我之前就是被一个僵尸python进程坑了。
之前跑7B也遇到过类似情况,A10上18G加载完实际可用的碎片化内存没你想象那么多,vLLM的KV cache会按最大并发预留,3-4个请求同时进来直接爆很正常。你把--max-num-seqs显式调低到2试试,别只改并发数,另外--gpu-memory-utilization0.9配合--max-model-len4096其实挺吃紧的,AWQ精度没问题,但量化后显存占用不是线性的。我后来直接换成GPTQ加--kv-cache-dtype fp8才稳下来,你可以先看下vLLM的日志里实际KV cache分配了多少。
这问题大概率不是显存不够,是vLLM的KV cache跟并发数没匹配好。--gpu-memory-utilization 0.9看着像调了,但7B模型在A10上本身KV cache就吃紧,3-4个并发加上长上下文很容易爆。你可以先试试把--max-num-seqs降到2或3,或者干脆限制--max-model-len到2048,看OOM还出不出。另外AWQ精度没问题,但记得确认下是不是加载时没走量化权重,有时候配置没对上也会莫名多占显存。