最近在用vLLM部署Qwen2.5-7B-Instruct,显存是24G的4090。单卡部署,开了--max-model-len 8192,--gpu-memory-utilization 0.9,平时单请求没问题,延迟30ms左右。但一上并发(比如20个请求同时进来),显存直接飙到23.5G然后OOM,进程崩了。
vLLM部署Qwen2.5-7B,并发一高就OOM,是我显存分配姿势不对吗?
全部回复
共 62 条你这配置单请求30ms说明模型本身没问题,但并发OOM大概率不是显存分配姿势的事。vLLM的KV cache是按最大并发数预分配的,20个请求同时进来,每个请求的KV cache都会按8192长度占满,24G确实扛不住。试试把--max-num-seqs调低到8或者16,或者把--gpu-memory-utilization降到0.7,给KV cache留点余量,同时把--max-model-len缩到4096,吞吐影响不大但能省不少显存。我这边之前跑7B也是这样,后来干脆开了--enable-prefix-caching,长对话场景下显存占用稳很多。
这问题我上周刚踩过,--max-model-len 8192加--gpu-memory-utilization 0.9看着没问题,但并发时KV cache是按请求峰值预留的,20路同时进来直接吃满。你试试把--max-num-seqs调小到4或者8,再配合--swap-space给CPU留点缓冲,基本能稳住,代价是吞吐会降一点,但至少不崩。另外留意下vLLM版本,0.6.x之后对显存调度改了不少,升级到最新版可能本身就缓解了这个问题。
24G跑7B还开0.9的显存利用率,说实话有点赌运气了。qwen2.5-7B的KV cache在8192长度下本身就吃得很凶,20并发相当于瞬间要分配20份不同长度的KV块,vLLM的预分配机制会直接按最大可能去预留,哪怕实际用不到那么多。我建议你先试着把gpu-memory-utilization降到0.8以下,给pytorch的缓存和CUDA context留点余量,不然光是碎片化就能把显存顶穿。另外你确认过vLLM版本吗?0.6.x和0.7.x在paged attention的块管理上差异挺大的,有些旧版本在并发突增时不会及时释放已完成的请求块,容易造成峰值叠加。还有个思路是开--enable-chunked-prefill,把长prompt拆成小块,虽然会牺牲一点吞吐但能平滑显存曲线。最后问一下,你观察过OOM是发生在请求处理中还是排队阶段?如果是后者,那可能是max-num-seqs没设对,默认256会让vLLM一次性把太多请求塞进调度器。
20并发才崩其实不算意外,7B模型光权重就占14G左右,你给了90%显存,留给KV cache的也就7-8G,8192长度下每个请求的KV cache差不多要几百MB,20个并发直接吃满很正常。我之前用4090跑同款模型,开--max-model-len 4096,--gpu-memory-utilization 0.92,并发压到12个才稳,你这个配置其实已经踩在临界点了。
有个小技巧你可以试试,vLLM支持--enable-chunked-prefill,能把长prompt的预填充拆成小块,虽然单请求延迟会稍微高一点,但并发时显存峰值能平滑不少。另外检查下是不是没有开--swap-space,默认0的话,显存溢出去连CPU offload的机会都没有,直接崩。
还有就是,20并发对7B模型来说其实有点苛刻,vLLM的continuous batching虽然高效,但每个sequence的KV cache是硬性开销,不如把--max-num-seqs调小点,比如8-10,配合--max-num-batched-tokens限制一下batch总长度,牺牲一点吞吐换稳定。
我后来干脆换成了AWQ量化版,显存直接降到11G,KV cache能多分一倍,实测30并发也才用满17G,不过精度损失得你自己评估,代码生成任务还行,聊天场景偶尔会有点飘。
你单请求30ms延迟其实挺好了,说明模型加载和算子都没问题,问题纯粹在KV cache的分配策略上。建议先跑个vllm benchmark的脚本看看不同并发下的显存曲线,再决定是砍模型长度还是砍并发数。
最后问下,你用的是vLLM哪个版本?老版本0.4.x的显存管理确实粗糙,升到0.6.x之后paged attention的块分配优化了不少,同样配置能多扛30%的并发。
试试把gpu-memory-utilization降到0.7,给vLLM的显存缓存留点余量,另外max-num-seqs调低到8。
24G跑7B还开0.9利用率,并发一上来必然爆显存啊,这跟姿势没关系,是vLLM的预分配机制就这样。你可以试试把gpu-memory-utilization降到0.7左右,给KV cache留点余量,或者干脆开--enable-prefix-caching,重复前缀能省不少。另外20并发对7B来说有点狠了,你确认下是不是max-num-seqs没设,默认值可能太高了。我之前用同样配置跑过,把max-num-seqs调到8,并发100都没崩过。
试试把max-model-len降到4096,这参数吃显存比想象中狠,并发时KV cache直接爆了。
看到这个问题我第一反应是,24G跑7B按理说余量挺大的,但20并发就炸确实不正常。你试试把gpu-memory-utilization降到0.8看看,因为vLLM预分配显存是按峰值来算的,0.9意味着它会把KV cache预留到接近极限,并发一高,每个请求的KV cache叠加起来就直接击穿天花板了。另外你max-model-len设的8192对7B来说不算短,实际推理时如果输入输出长度波动大,vLLM是按最大可能长度去预分配每个sequence的显存,而不是按实际使用量,所以并发20个哪怕每个都很短,它也会按8192这个上限去算。我上次用A100跑同模型也踩过类似坑,后来把max-num-seqs参数限制在4~8,同时开了enable-prefix-caching,情况好了很多。你其实可以先用API观察一下启动日志里KV cache的预估大小,然后按并发数反推一下每个seq的显存占用,比瞎调参数靠谱。对了,你用的是最新版vLLM吗?老版本在显存管理上有个已知的碎片化问题,升级到0.6.3之后会有明显改善。
我之前也踩过类似的坑,24G显存跑7B按理说很宽裕,但vLLM的预分配机制会按max-model-len一次性把KV cache占满,你设了8192长度,并发20个请求的峰值token数其实远超这个数,导致OOM。建议把gpu-memory-utilization降到0.75左右,同时加个--max-num-seqs限制一下同时处理的序列数,比如8-12,这样能有效控制显存峰值。另外可以试试开--enable-chunked-prefill,对小并发场景显存压力会小很多。
这问题我踩过一模一样的坑,--gpu-memory-utilization 0.9不是给KV cache留了多少,而是给权重留了多少,并发上来KV cache直接爆。试试把--max-num-seqs限制到4或者8,再配上--max-num-batched-tokens,比硬调utilization管用。另外Qwen2.5的GQA本身KV cache就小,你这24G按理说够20并发,但vLLM默认的preemption策略在OOM边缘很蠢,建议加--enable-prefix-caching看能不能救一下。
如果还不行,干脆开--quantization awq或者用GPTQ的4bit版本,速度损失不大,显存直接砍一半,我自己的7B模型就是这么稳下来的。别迷信单请求的低延迟,并发下显存分配才是真瓶颈。
20并发直接打满23.5G,这明显不是gpu-memory-utilization的锅,vLLM的KV cache是按最大并发数预分配的。你只设了max-model-len没限制max-num-seqs,默认情况下它可能按很激进的batch去预留空间,试试显式加个--max-num-seqs 8或者更低,应该能压住峰值。另外8192长度对7B来说有点奢侈,如果实际业务没那么长,砍到4096能省出一大块缓存留给并发。我之前用同卡跑类似模型,把max-num-seqs压到4,20并发稳得很,延迟也就多个十几ms。
20并发就把23.5G吃满然后崩了,这不太正常,我怀疑不是显存分配问题,而是KV cache的预分配策略在作祟。你试试把--max-num-seqs调小一点,比如8或12,这参数会限制同时处理的序列数,能直接把峰值显存压下来。另外,--gpu-memory-utilization 0.9其实留的余量有点少,建议降到0.85,给torch的碎片化分配留点缓冲,不然高并发时显存碎片也会触发OOM。我之前用A100跑类似模型,就是靠这两个改动稳住的。
这问题我上周刚踩过,vLLM的KV cache是按最大并发预分配的,你设0.9利用率基本等于把显存全留给缓存了,但Qwen2.5的attention计算本身也要吃临时显存,并发一高就炸。建议先把gpu-memory-utilization降到0.75试试,或者显式加个--max-num-seqs 8限制一下batch大小。另外可以开下--enable-chunked-prefill,长请求的prefill阶段会分块处理,峰值显存能降不少。我这边同样24G卡跑7B,现在并发16稳得很。
OOM这个现象挺典型的,20并发对7B来说不算小,但24G按理说够用。你试试把gpu-memory-utilization降到0.85,然后加个--max-num-seqs 8限制一下同时处理的序列数,给显存留点缓冲。另外检查下是不是max-model-len设太长导致KV cache膨胀,8192对7B来说确实有点吃紧,如果业务允许砍到4096能省不少。我之前跑同款模型用类似配置,并发压到16就稳了,你可以先拿这个组合试试看。
显存利用率开到0.9再加上默认的预分配策略,vLLM会一次性把KV cache占满,并发一高自然容易爆。建议试下--max-num-seqs限制并发数,或者把--gpu-memory-utilization调到0.7左右留点余量,另外检查下是不是没开--enforce-eager导致CUDA graph也吃显存。我之前跑同模型用这些参数配合--swap-space,20并发稳得很。
这大概率不是显存分配的问题,是vLLM的KV cache预分配策略在作怪。你设了0.9利用率,但20并发时每个请求的KV cache会按max_model_len动态申请,瞬间峰值就爆了。可以试试把--gpu-memory-utilization降到0.7,同时加--max-num-seqs 16限制并发数,让vLLM在池子里排队而不是全塞进来。另外也可以考虑开--enable-prefix-caching,复用公共前缀的KV cache,能省不少显存。我之前跑13B模型遇到类似情况,限流后稳得很。
这题我好像也踩过,gpu-memory-utilization设0.9太满了,vLLM还要留一点给KV cache和CUDA context,并发上来直接爆。你可以试试把max-model-len降到4096,或者给--max-num-seqs设个8,给推理留点余量。另外检查下是不是用的默认的continuous batching,有时候并发高会触发新的显存分配,不如直接限制一下。
你这个配置单请求30ms挺正常的,但并发20个直接OOM大概率不是显存分配的问题,是vLLM的KV cache和prefill阶段峰值叠加了。试试把--max-num-seqs调小到8或者4,再开个--enable-chunked-prefill,能明显平滑显存波动。另外gpu-memory-utilization0.9有点激进,留个1-2G给PyTorch和CUDA context反而更稳,我之前用0.85跑13B模型并发32都没崩过。
还有个细节,Qwen2.5的attention实现是GQA,KV cache占用比MHA小很多,但如果你没指定--kv-cache-dtype,默认fp16在长上下文下也吃显存。可以试试--kv-cache-dtype fp8,虽然精度略降,但24G卡上能多扛不少并发。
我猜你可能是直接用的默认调度策略,vLLM在并发高时会为每个请求预分配最大长度的KV cache,实际用不满但显存已经占死了。把--max-model-len降到4096试试,除非业务真的需要8K上下文,不然这个参数对显存影响比并发数还大。
你这配置看着没啥大问题,但vLLM的显存分配不只是看max-model-len,还得留意KV cache的预分配策略。20并发对7B模型来说不算夸张,建议试试把--max-num-seqs调小点,比如4或8,让vLLM别一次性预留太多batch空间。另外也可以开--enable-chunked-prefill,能缓解并发时的显存峰值。要是还崩,干脆降到0.85的gpu-memory-utilization,留点余量给碎片。
这题我熟,之前用vLLM跑别的7B模型也踩过同样的坑。你光调gpu-memory-utilization没用,并发高的时候KV cache才是大头,建议把--max-num-seqs调小点,比如默认256改成32或64,给每个请求预留的显存就宽裕多了。另外可以试试开--enable-chunked-prefill,配合--max-num-batched-tokens限制一下,我这边同样24G卡,20并发稳得很。还有个小细节,--max-model-len别给太高,8192其实挺吃显存的,如果不依赖超长上下文,砍到4096能省出不少。