最近在折腾本地部署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 条你这情况我遇到过类似的,多半不是代码问题,vllm的显存管理对int4支持有时候确实会抽风。可以试试把gpu_memory_utilization降到0.7,然后换用最新版vllm,老版本对量化模型的内存回收有bug。另外确认下是不是prompt里带了很长的system内容,长上下文下KV cache膨胀得特别快,max_num_seqs调小到16试试。实在不行换llama.cpp部署,虽然吞吐低点但显存控制稳很多。
建议直接看下vllm的日志里有没有kv cache eviction的告警,另外试试paged attention的block大小调小点。
这问题八成是block管理器没回收旧token,试试升级到最新版vllm或者换个backup引擎比如sglang。
八成是prompt太长把KV cache喂饱了,试试限制max_model_len或者换AWQ量化版。
vllm那个动态管理只对短请求有效,长文本并发起来照样爆,用sglang或者加张卡吧。
之前跑Qwen2.5 7B也遇到过类似情况,int4量化下vllm的显存管理确实不如fp16版本那么可控,特别是长上下文时paged attention的碎片化问题会放大。你试试把gpu_memory_utilization降到0.8,同时把max_num_seqs调成32,这俩参数对显存峰值影响很大。另外确认下是不是用了最新版vllm,旧版对量化模型的支持有bug,升级到0.6.1以上会好很多。如果还不行就换exllamav2或者llama.cpp,7B量化版用单卡跑反而更稳。
我之前也踩过类似的坑,vllm的显存管理其实对量化模型支持没那么好,int4的KV cache计算方式跟fp16不一样,容易把预留的显存吃满。建议你先看看是不是Prompt长度波动太大,把max_model_len设成固定值(比如4096)再试试,另外gpu_memory_utilization降到0.8给CUDA留点余量。我后来换成了SGLang,同样的模型和并发下显存稳定很多,你可以对比测一下。
说实话你这配置跑7B int4应该很富裕才对,两张4090总共48G,按理说就算塞满长上下文也不至于这么快就爆。我怀疑问题不在max_num_seqs或者gpu_memory_utilization,而是你那个int4量化版本本身可能不是vllm官方支持的格式,比如GPTQ或者AWQ的kernel在动态显存管理上会有一些坑,之前我遇到过类似情况,换回fp16或者bf16用官方量化方式就正常了。另外你可以试试直接看vllm的日志,如果提示的是“KV cache blocks”一直在增长,那就是preemption和swap没生效,这时候可以检查一下是不是没开enable_prefix_caching,或者把max_num_batched_tokens设得太低反而导致调度器频繁分配新block。还有个排查思路是盯一下单次请求的输入长度,是不是有某些prompt特别长,比如超过8K,这样即使并发小也会把显存顶穿。我自己的经验是,如果主要跑短文本多并发,可以试试把gpu_memory_utilization降到0.7,强制预留更多显存给torch的碎片整理,反而更稳定。要是实在折腾不出来,可以换个思路用llama.cpp的server模式,虽然吞吐低点但显存控制是硬上限,不会出现这种缓慢泄漏式的OOM。
我之前也踩过这坑,vllm的显存管理其实对int4支持不算太友好,你试试把gpu_memory_utilization降到0.8,同时给两块卡分别设max_num_seqs=32,有时候单卡压力小点反而稳定。另外检查下是不是prompt里带的长上下文被重复计算了,Qwen的cache策略对多轮对话挺吃显存的。实在不行就换TGI或者llama.cpp,7B量化版用后者部署省心不少,就是吞吐低点。
显存涨说明有请求没释放,试试加--enable-prefix-caching或者降并发,int4用vllm有时确实会这样。
我之前也踩过类似的坑,vllm那个动态显存管理其实更偏向于KV cache的复用,但你连续跑几十个prompt之后OOM,多半是长文本场景下prefill阶段显存峰值没控制住。7B int4虽然模型本身不大,但max_num_seqs=64意味着最多同时缓存64条序列的KV,如果每个prompt都带很长的对话历史,KV cache累积起来非常恐怖,24G*2看着多其实撑不住。你调低max_num_batched_tokens没用是因为它只限制单batch的总token数,但vllm默认会按seq粒度来做continuous batching,只要seq数没降,显存照样涨。建议先看看是不是有prompt特别长,比如超过2k或4k,可以试试把max_num_seqs降到16甚至8,同时把block_size调小到16或32,这样显存分配粒度更细,能缓解尖峰。另外检查下有没有开enable_prefix_caching,如果没开的话,重复的前缀每次都会重新算KV,显存自然越堆越多,打开之后能复用部分结果。如果还是不行,换llama.cpp或者sglang试试,sglang在长上下文下的显存控制比vllm激进一些,就是用起来不如vllm顺手。最后可以看下nvidia-smi里的进程,确认是不是有两张卡负载不均,vllm有时候默认只把第一张卡塞满了才开始用第二张。
检查下vllm版本,老版本动态显存有bug,升到0.6.2以上基本能解决。
你这个现象我前两天刚踩过一模一样的坑,最后查出来其实不是vllm动态分配没生效,而是int4量化版在加载时如果没走awq或者gptq的专用kernel,算子会回落到fp16的权重上跑,显存占用直接翻倍。你可以先nvidia-smi看一眼每个进程的实际显存,如果峰值稳定在40G以上而不是缓慢涨,那大概率就是量化格式没被正确识别。另外两个细节:max_num_seqs=64对7B来说太激进了,尤其在长文本场景下,每个seq的kv cache会随长度线性膨胀,建议先压到16或者32试;还有gpu_memory_utilization调太高反而会触发vllm的预分配,它会把剩余显存全部吃满来建cache,如果模型权重本身占了11G左右,那46G爆掉基本就是cache算错了。排查的话可以开vllm的--enable-prefix-caching,配合prompt里加个固定system消息,能显著减少重复前缀的显存开销。要是还不行,我建议换sglang试试,它有个radix cache机制,对这种多轮短prompt场景友好很多,我同样的配置跑起来峰值能省7-8G。
4090双卡还爆大概率是paged attention没吃到block,试试把max_num_seqs降到16并开enable_prefix_caching。
你量化版是不是用的AWQ?换GPTQ或者直接上FP8看看,vllm对int4支持偶尔有显存泄漏的老坑。
说实话你这配置跑7B int4按理说绰绰有余,问题大概率出在vllm的预分配策略上。你gpu_memory_utilization设0.9等于给KV cache留了太大空间,多请求时cache不断增长但显存不会自动回收,建议先降到0.6试试。另外max_num_seqs=64对7B来说偏高了,并发多的时候prefill和decode混在一起很容易撑爆,改成16或者32能缓解不少。我之前遇到过类似情况,最后是加了个--enforce-eager参数关掉CUDA graph才稳住的,虽然吞吐会掉一点但至少不OOM。
八成是连续请求里长序列把KV cache撑爆了,试试限制单条prompt长度或者换个AWQ量化版看看。
之前也遇到过,vllm那个显存管理对长文本并发挺吃紧的,直接上多卡张量并行或者换llama.cpp更稳。
之前跑Qwen2.5 7B也遇到过类似情况,动态显存管理在长上下文下确实会先吃满cache再触发释放,建议试试把gpu_memory_utilization调到0.85以下,给碎片留点余量。另外排查下是不是prompt里有特别长的序列,单条长度超过2048就会让KV cache翻倍,你可以用vllm的--enable-prefix-caching看看命中率。实在不行就换llama.cpp配合flash attention,单卡跑int4能稳很多,就是吞吐低点。
我之前也踩过类似的坑,跟你分享下排查结论:vllm的动态显存管理不是万能的,它只在预分配池内做复用,OOM往往是KV cache和激活值把池子撑爆了。你设了gpu_memory_utilization=0.9,两张卡其实是各自独立算的,单卡显存利用率90%意味着每张卡留了2.4G给碎片和上下文,但int4量化后模型权重占8G左右,KV cache按你max_num_seqs=64和默认max_model_len算,单卡很容易就吃满剩余空间。我猜问题大概率出在max_model_len没显式设,7B模型默认可能是32K甚至更长,长prompt下每个seq占用的KV cache会指数级增长。你可以先跑个不带vllm的纯transformers测试,对比看是不是推理逻辑本身有显存泄漏,同时用nvidia-smi盯一下是哪个张量在涨。另外,你两张卡有没有开tensor parallel?如果没设tensor_parallel_size=2,vllm默认只用一张卡,另一张空闲,但显存统计会按两张卡合计报错,这个很容易误导。轻量方案的话,可以考虑换AWQ或GPTQ的4bit,配合flash-attention和paged attention,把max_model_len锁到4096试试,或者干脆用llama.cpp的server,虽然吞吐低点但显存曲线稳很多。
显存碎片化了吧,vllm的paged attention对长上下文多并发还是会有峰值,试试把gpu_memory_utilization降到0.8留点buffer。
我之前也遇到过类似的坑,问题大概率不在max_num_seqs上,而是gpu_memory_utilization=0.9配合vllm的默认KV cache预留策略,在长上下文连续请求下会不断膨胀,尤其int4量化后显存碎片化会更明显。你可以试试把max_num_batched_tokens调回默认值,然后限制每个请求的最大长度,或者换用--enable-prefix-caching试试。如果还不行,干脆上sglang或者exllamav2,同样量化下显存占用能再降个20%左右。
我也遇到过类似情况,7B int4在vllm上长prompt多并发确实容易显存慢慢爬。你可以先看下是不是开了enable_prefix_caching或者block_size设太大,KV cache碎片化会导致显存回收不及时。另外max_num_seqs=64对两张4090来说有点激进了,试试降到16-24,配合max_model_len限制一下。实在不行换SGLang或者llama.cpp的server,轻量场景下稳很多。