最近在折腾本地部署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 条试试把gpu_memory_utilization调到0.85,同时限制一下单次请求的最大长度。
可能是vllm的预分配策略和量化模型兼容有问题,试试把gpu_memory_utilization降到0.85。
试试把gpu_memory_utilization降到0.8,或者加个--enforce-eager参数看看。
这问题我也遇到过,vllm的显存管理确实不是完全自动的,尤其在4090这种非NVLink互联的卡上,跨卡通信本身就有额外开销。你设的gpu_memory_utilization=0.9其实挺激进的,建议先降到0.75试试,给paged attention的显存碎片留点余量。另外max_num_seqs=64对于7B模型有点大了,实测20-30左右更稳,因为int4量化版虽然模型体积小了,但kv cache依然会随着并发请求数线性增长。还有个小细节,vllm默认会缓存所有请求的中间状态,如果prompt长度差异大,老请求没释放完新请求又进来了,显存就像滚雪球。建议检查一下是否开启了enable_prefix_caching,这个功能在长文本场景下反而容易累积占显存。如果还是爆,可以试试用TGI或者llama.cpp的server模式,后者对单卡显存控制更暴力,缺点是并发吞吐不如vllm平滑。
试试把gpu_memory_utilization降到0.85以下,同时把max_num_seqs调到32,vllm的预分配机制在量化模型上容易算不准。另外7B int4在4090上单卡跑都够呛,长文本场景下建议开--enforce-eager模式禁用CUDA图优化,能省点显存。如果还不行,换llama.cpp或者ExLlamaV2这种非框架方案,推理效率更高。
老实说,我遇到过几乎一模一样的情况,vllm那个“动态显存管理”真没那么智能,尤其是在多并发和长文本场景下。你设的gpu_memory_utilization=0.9其实是让vllm预留90%的显存做缓存,但int4 7B模型本身占不到那么多,剩下的空间其实是被它用来缓存KV cache,而且越积越多不会主动释放,所以连续请求多了自然就涨到OOM。一个比较实用的办法是把max_num_seqs调小到16甚至8,同时把gpu_memory_utilization降到0.75左右,虽然牺牲一点吞吐,但至少不会跑着跑着崩掉。另外你可以试试开启--enable-prefix-caching,如果prompt有重复前缀的话能省不少显存。如果还是不行,我建议换成llama.cpp配合server模式部署,量化版模型用这个框架显存控制更硬核,虽然并发不如vllm高,但胜在稳定,不会突然就爆。还有个偏方是给vllm加上--swap-space参数,让它在显存不够时往内存里换页,不过性能会降一截。总之你这个配置按说两张4090跑7B不至于轻易OOM,大概率是vllm默认的调度策略对长文本连续请求处理得比较笨。
显存持续上涨这块,可以试试把gpu_memory_utilization降到0.8以下,给vllm的调度留更多余量,另外检查下是不是prompt长度差异太大导致缓存碎片化。我之前用7B量化版在双卡上遇到过类似问题,后来把max_num_seqs降到16配合--enforce-eager模式反而稳定了。如果还不行,可以看看是否重复调用了tokenizer导致内存泄漏,或者切到TGI试试,它对长文本并发处理更保守些。
有没有更详细的教程推荐?
学到了,感谢分享!
这问题我也踩过坑,vllm的显存管理其实不是完全自动的,它那个gpu_memory_utilization=0.9是对应单卡总显存的比例,你两张卡加起来46G它其实只认单卡的90%也就是21.6G左右,剩下的被预留给KV cache和模型权重了,但int4量化后权重本身不大,问题可能出在max_num_seqs=64上,这个值对于7B模型来说偏大了,尤其如果prompt长度参差不齐,vllm为了凑batch会拼命缓存中间状态,导致显存像雪球一样滚上去。建议你先试试把max_num_seqs降到16或者8,同时开一下enable_prefix_caching看看能不能复用之前的计算结果,另外检查一下vllm的版本,0.6.x以后对动态释放优化了不少。如果还不行,换个思路试试llama.cpp的server模式,它虽然吞吐低一点但显存控制极其稳定,我拿它跑同样的模型从来没OOM过,只是并发量要控制在10个以内。
显存一直涨到OOM大概率不是代码问题,vllm的动态管理主要针对单次推理,你这种连续请求场景下,它不会主动释放历史占用的缓存。建议把gpu_memory_utilization降到0.8以下,同时试试加--enable-prefix-caching参数,能复用部分计算。如果还不行,换个思路用llama.cpp加载GGUF格式的Qwen2.5,单卡就能跑,显存控制更稳。
说实话你这个问题挺典型的,vllm那个动态显存管理其实不是完全自动的,它对长文本和并发量的处理有点“粗放”。你设了gpu_memory_utilization=0.9,但两张4090总共48G,它默认会把90%也就是43.2G都预占掉,加上量化版模型本身大概4-5G,再跑几十个prompt时如果每个序列长度不均,显存碎片化就会让实际可用空间收缩得很快,最后OOM。我建议你先试试把gpu_memory_utilization降到0.7或者0.8,给系统留点缓冲,同时把max_num_seqs砍到32甚至16,别贪并发。另外你提到调了max_num_batched_tokens没效果,这参数其实更影响吞吐而不是显存峰值,真正吃显存的是每个请求的max_model_len,如果你没显式设置,vllm默认会用模型支持的最大长度,比如8192,长文本场景下这很要命。可以手动设成4096或者2048试试,代价是超长输入会被截断。如果这些都不行,短期最轻量的方案是换exllamav2或者llama.cpp,单卡就能跑,显存管理更直接,但吞吐会低一些。长期来看,7B模型在双卡下确实容易因为显存碎片化翻车,可以考虑上量化到4bit的AWQ版本,配合vllm的prefix caching功能,能省不少事。
试试把gpu_memory_utilization调到0.85,留点余量给vllm的动态分配。
跟你情况类似,我后来发现是vllm默认的prefill阶段显存分配策略在长上下文场景下容易失控。试试把gpu_memory_utilization降到0.8以下,同时加上--enforce-eager参数跳过CUDA图优化,虽然会牺牲一点吞吐,但显存稳定很多。另外Qwen2.5的int4量化版用AWQ格式会比GPTQ更省显存,可以重新量化试试。
看到你这个情况我第一反应是vllm的预分配机制可能跟量化模型不太兼容,int4版本虽然显存占用低了,但vllm内部可能还是按fp16的显存预算去预留空间,导致实际可用内存被高估了。我试过类似配置,gpu_memory_utilization设到0.9对量化版来说太激进了,建议先降到0.75左右跑跑看,或者把max_num_seqs砍到32甚至16,毕竟7B模型连续处理时kv cache膨胀很快。另外可以检查下是否启用了prefix caching,这个特性在多prompt场景下反而会额外吃显存。如果还不行,不如试试exllamav2或者llama.cpp的server模式,它们对显存的控制更精细,特别是llama.cpp能精确设定上下文长度,vllm的“动态管理”在长序列下确实有点玄学。对了,你用的vllm版本是多少?0.4.0之后有个关于block manager的改动,老版本可能确实有泄漏问题。
显存慢慢涨到OOM大概率是vllm的prefill阶段缓存没及时释放,或者max_num_seqs开太高导致连续请求堆积。可以试下把gpu_memory_utilization降到0.8,同时加上--enforce-eager参数禁用cuda graph,能缓解一些。另外int4模型其实可以用AWQ或GPTQ量化版本,配合exllamav2推理,4090单卡跑7B长文本很稳,基本不会爆显存。
显存涨到OOM大概率不是代码问题,而是vllm的page attention在连续请求时会累积缓存,尤其你设了64个并发,int4模型每层权重虽然小了,但kv cache占得其实不少。可以试试把max_num_seqs降到16或者32,同时把block_size改成16(默认是16的话就再调低点),另外检查下vllm是不是用了最新的release版本,之前有过内存泄漏的bug。如果想省心,也可以考虑换llama.cpp或者exllamav2,这两对显存控制更直接一些。
我最近也遇到过类似情况,vllm那个动态显存管理在长序列下其实挺容易翻车的,尤其是量化版的Qwen2.5 7B,推理时内部计算图还是会临时分配大量显存。你可以试试把gpu_memory_utilization调到0.7以下,强制预留更多余量,或者直接换成AWQ量化版配合ExLlamaV2部署,同样精度下显存占用更可控。另外如果单请求长度超过2048,max_num_batched_tokens设低了反而会导致频繁重组batch,增加碎片化占用,不如先测下短文本场景是否稳定。
说实话你这配置挺豪华的了,双4090跑7B int4按理说绰绰有余。我觉得问题大概率出在vllm的显存预分配机制和量化版本的兼容性上。int4量化后的qwen2.5虽然模型体积小了,但vllm内部可能还是按照原始参数去申请KV cache空间,再加上你设的max_num_seqs=64对7B来说偏大,每个序列的缓存叠加起来很容易撑爆。我建议你先试试把gpu_memory_utilization降到0.7或0.8,同时把max_num_seqs砍到16或32,看看显存会不会平稳。另外有个细节——vllm对量化模型的显存回收有时候确实不干净,尤其是在连续请求间隔很短的时候,可以手动在每次请求后加个torch.cuda.empty_cache()或者用vllm的--enable-chunked-prefill选项来分段处理,能缓解不少。如果还是不行,可以试试用transformers+bitsandbytes直接加载,虽然吞吐量低点,但显存控制更透明,或者换llama.cpp的q4_k_m量化方案,那个在长文本场景下的内存管理比vllm稳定。
可能是max_num_seqs设太高了,减到16试试,4090双卡跑7B int4没必要开64并发。