最近在折腾本地部署Qwen2.5 7B(int4量化版),用的vllm框架,服务器是两张RTX 4090(24G),设置了max_num_seqs=64和gpu_memory_utilization=0.9。刚开始跑几个请求还挺正常,但连续处理几十个prompt之后,显存就慢慢涨到46G然后直接OOM了。查了vllm的文档说是有动态显存管理的,但感觉没生效。我试过调低max_num_batched_tokens到2048,也没用。是不是我哪里设置不对?还是7B模型本身在长文本多并发下就是容易爆显存?求大佬们指点一下排查思路或者有没有其他轻量部署方案推荐。
用vllm部署Qwen2.5 7B,显存一直涨到OOM,是代码有问题吗?
全部回复
共 159 条我之前跑Mixtral也遇到过类似情况,后来发现是vllm的prefix caching没关,连续请求带重复前缀时显存会越堆越多,你试试--disable-prefix-caching看看。另外int4量化版本其实对显存压力不大,46G暴涨更像是在做显存碎片整理,可以把--swap-space设成0或者换paged attention的block大小。实在不行就换llama.cpp的server模式,虽然吞吐低点但显存控制稳得多。
我之前也踩过类似的坑,int4其实不是显存问题的关键,vllm的paged memory那块儿对量化模型支持有时候会抽风,建议先试试把gpu_memory_utilization降到0.7,留点余量给碎片。另外检查下是不是prompt里带了很多历史对话,长序列下KV cache膨胀很快,可以开一下enable_prefix_caching看看有没有改善。如果还不行,换transformers+accelerate跑单卡试试,虽然慢点但至少稳定。
试试把gpu_memory_utilization降到0.7,留点显存给碎片,我上次这么调就好了。
vllm的预分配和显存碎片叠加了,换awq量化或者限制单条max_len到1024能压住。
我之前也踩过类似的坑,vllm那个动态显存管理其实不是无限膨胀的,它默认会预分配KV cache,你设了0.9的utilization,两张卡一共43G左右可用,但int4 7B的权重也得占6-7G,剩下空间其实挺紧张。你连续跑几十个prompt,如果每个序列长度都挺长,KV cache增长很快,尤其max_num_seqs=64有点激进,并发一高,显存碎片化加上预分配没及时释放,OOM就正常了。建议先把gpu_memory_utilization降到0.8,同时把max_num_seqs调小到32试试,另外检查下是不是prompt里带了system token导致实际输入长度比你想象的长。还有个排查办法,开vllm的--enable-prefix-caching,如果请求有公共前缀能省不少显存。至于轻量方案,我后来换了llama.cpp的server模式,配合flash attention,同样int4下显存占用稳定很多,虽然吞吐低点,但不容易爆。你也可以看看是不是pytorch版本和vllm不兼容,我之前2.1.0配vllm 0.4.2就出过类似泄漏问题,升级到0.5+就没事了。
显存涨到OOM大概率是vllm的prefix cache没关,试试--disable-prefix-caching。
遇到过类似情况,先别急着怀疑代码。你设了gpu_memory_utilization=0.9但两张卡是独立分配的,vllm默认不会自动均衡跨卡显存,单卡压力其实很大。建议试试把tensor_parallel_size设成2,或者直接降成单卡部署再加--enforce-eager模式,能省不少显存。另外int4量化版在vllm里有时候反而比fp16更吃显存,因为要额外存量化参数,可以换个思路用llama.cpp的GGUF格式跑跑看,长文本场景下更稳。
你这情况我上周刚踩过坑,vllm那个动态显存管理其实对int4支持得没那么好,尤其是长上下文时KV cache会偷偷吃满。建议先把gpu_memory_utilization降到0.7试试,同时看看是不是prompt长度波动太大导致显存碎片化。另外可以开一下vllm的日志看具体哪一步涨的,我之前发现是prefill阶段爆的,最后换个量化方式比如AWQ就稳了。
我之前也踩过这个坑,vllm的显存管理对int4量化支持其实没那么完美,特别是长上下文下KV cache会吃得很猛。你试试把gpu_memory_utilization降到0.8,然后给max_num_seqs砍到32,同时跑之前先预热一下看峰值。另外检查下是不是prompt里带了特别长的system指令,有时候单条请求的显存峰值比多并发还吓人。如果还不行,可以换TGI或者llama.cpp的server模式试试,7B量化版用llama.cpp其实挺稳的。
这情况我遇到过,vllm的显存管理不是完全自动的,你那个gpu_memory_utilization=0.9得配合max_num_seqs调,64对于7B来说有点激进,我建议砍到32试试。另外int4量化版在vllm里有时候会额外吃显存做反量化缓存,可以换awq或者gptq的版本看看。还有一种可能是你prompt长度差异大,vllm会为了长序列预留空间,试试加个--enable-prefix-caching或者把max-model-len设小一点,比如4096,能省不少。如果还不行,直接换sglang,同样支持量化,显存控制更稳。
这题我好像也遇到过,感觉不一定是代码的锅。vllm那个动态显存管理对int4支持其实挺迷的,有时候量化权重没吃满但KV cache会跟着并发数疯涨,你max_num_seqs拉到64有点激进了,两张卡的话每张留个2G多给碎片和临时张量比较稳。另外可以看看是不是prefill和decode互相挤占导致的,试试把max_num_batched_tokens调成跟seq长度挂钩,或者干脆用--enforce-eager关掉CUDA graph,虽然会慢点但显存占用能降不少。要是还不行,换TGI或者SGLang跑跑看同配置,对比下就知道是不是vllm自己的问题了。
说实话你这个现象我上周刚踩过一模一样的坑,最后查下来不是vllm动态管理失效,而是int4量化版的权重虽然小了,但KV cache和中间激活值依然按原始精度算,7B模型长文本下激活值膨胀特别猛。你设的gpu_memory_utilization=0.9其实意味着vllm会提前把所有可用显存都预留给KV cache池,但问题是它不会因为实际请求少就释放,而是持续占着,等你并发一多,再加上前缀缓存没命中,就容易在某个峰值瞬间爆掉。我后来把gpu_memory_utilization降到0.7,同时把max_num_seqs砍到32,再把--enable-prefix-caching打开,就没再OOM过。另外你提到max_num_batched_tokens调低没用,我怀疑是vllm版本问题,有些老版本对量化模型的前向分配逻辑有bug,建议直接升级到0.6.6以上,或者试试用--quantization awq配合专门的量化权重,比gptq的int4省显存更稳定。如果还不行,干脆换sglang,它对于这种突发流量场景的显存控制更“抠”,至少不会像vllm那样把整块显存都锁死。
说实话我第一反应是int4量化配vllm这个组合本身就有点怪,vllm对AWQ或者GPTQ的支持虽然没问题,但Qwen2.5的int4版本如果走的是autoawq,有时候量化参数和vllm的kernel版本不匹配会引发奇怪的显存碎片化。你试过把gpu_memory_utilization降到0.85以下吗?我遇到过类似情况,0.9这个值在双卡环境里反而容易让vllm预分配太多显存给KV cache,但实际跑起来又因为连续请求导致某些sequence的cache无法释放,最后累积到OOM。另外建议你监控一下每个request的max_model_len,如果prompt长度波动很大,vllm的动态调度会为长序列保留额外显存,但短序列回收不及时,你这个现象就很像显存碎片而非真正的容量不足。可以试试用--enable-prefix-caching或者把max_num_seqs调低到32,同时关掉continuous batching的某些优化项看看。如果还不行,换个思路,直接用transformers+flash-attention做离线推理,或者转成llama.cpp的GGUF格式,对于7B这种规模反而更稳,毕竟vllm优势在高并发和长文本,你这种场景可能有点大材小用。
量化版跑满并发显存涨挺正常,建议看看是不是prompt长度波动大,试试把max_model_len锁死。
别光调batch,把vllm的版本升到最新,老版本显存碎片化很严重,亲测有效。
同款配置踩过这坑,vllm的显存管理对int4支持确实有点迷,尤其长文本下KV cache涨得特别凶。你可以试试把gpu_memory_utilization降到0.8,同时给两张卡分别指定max_num_seqs=32,强制分摊负载,我这样调完跑两百多个prompt都没爆。另外建议开下--enable-prefix-caching,能省不少显存,如果还不行就换sglang,同量化下内存占用能再低个10%左右,速度也没差太多。
我之前也踩过类似的坑,排查下来发现是prompt长度波动太大导致KV cache预分配跟不上,加上int4量化下vllm的显存管理反而没那么激进。你可以试试把gpu_memory_utilization降到0.85,然后开一下--enable-prefix-caching,另外看看是不是某些长prompt触发了重新计算。还有个小技巧,把max_num_seqs调小到32,配合--max-model-len强制限制一下,基本能稳住。不过说实话7B在双卡上这么跑确实紧张,换个思路用llama.cpp的server模式或者跑一下量化到3bit的版本,可能会省心不少。
这情况我也踩过坑,vllm的显存管理对量化模型有时确实不按套路出牌。建议你先把gpu_memory_utilization降到0.7试试,同时关掉自动前缀缓存,有时候这俩和int4的算子有冲突。另外你两张卡是走张量并行还是数据并行?如果是后者,模型副本各自占内存,46G爆掉很正常。排查时盯着nvidia-smi看是哪个进程吃满,先排除是不是多卡通信缓冲没释放。实在不行换TGI或者llama.cpp的server模式,小并发下显存控制反而更稳。
试试把gpu_memory_utilization降到0.7再配个--swap-space,我之前这么搞就没爆过。
你这配置跑7B按理不该炸,试试把max_num_seqs砍到16,大概率是并发太高把KVCache撑爆了。
跑过类似的配置,4090双卡跑7B按理说余量挺大的。你这个问题更像是vllm的显存碎片化,而不是模型本身吃满,试下把gpu_memory_utilization降到0.7左右,留出一些冗余给KV cache的波动。另外max_num_seqs=64对于7B来说有点激进,砍到16或者32看看,长文本场景下并发太高很容易触发预分配。我之前换过用llama.cpp的server模式,显存占用稳定很多,就是吞吐量差点,但至少不OOM。你那些prompt的平均长度大概多少?如果经常超过2k token,建议单独用--max-model-len限制一下。
显存涨到OOM大概率是vllm的prefix caching没关,加上长上下文累积导致KV cache爆炸,试试把--max-model-len调小点。
我之前遇过类似问题,换用TGI部署同模型稳得多,4090单卡跑7B量化完全够用,双卡反而容易有显存碎片问题。