最近在用vLLM部署Qwen2.5-7B做内部demo,单卡A100 80G,模型用AWQ 4bit量化。平时单路请求挺流畅,但压测时并发到8左右,显存直接涨满然后OOM,日志里有“CUDA out of memory”。我已经设置了--max-model-len 8192,也开了--gpu-memory-utilization 0.9,但感觉还是不够稳。看了下nvidia-smi,好像KV cache占得特别凶,但我没手动调--max-num-seqs,这个是不是关键?还是说AWQ量化后显存占用模型本身还是太大,应该换成GPTQ或者干脆上8bit?另外,vLLM是不是对动态batch的显存预留机制有什么坑?求有经验的大佬指点下排查方向,或者分享下你们生产环境的类似配置。先谢过。
vLLM部署Qwen2.5-7B,并发一高就OOM,是量化问题还是我参数没调对?
全部回复
共 67 条这个场景我熟,--max-num-seqs确实得手动压一下,默认值在并发上来时会疯狂预分配KV cache,8并发直接爆很正常。AWQ本身没问题,但你可以试试把--max-num-seqs设成4或6,同时把--swap-space调低点,A100 80G跑7B量化绰绰有余。另外动态batching吃显存是动态的,建议开--enable-prefix-caching看看,能省不少重复计算。如果还炸,再考虑换8bit,但大概率不是模型本身的锅。
并发8就OOM确实不太像纯量化问题,A100 80G跑7B AWQ按理说余量很大。你试试把--max-num-seqs调小到4或者2,vLLM默认会预留很大batch空间,动态batching吃显存很猛,尤其KV cache是按最大并发预分配的。另外--gpu-memory-utilization 0.9建议降到0.8,留点给CUDA context和碎片,我之前遇到过类似情况,调这两个参数立马稳了。GPTQ和AWQ在显存占用上差别不大,不用急着换。
max-num-seqs确实得调,8并发对7B来说太小了,试着降到2或4看看。另外AWQ没问题,GPTQ也差不多,别折腾量化了。
max-num-seqs不调的话默认256,KV cache肯定爆,先限到8或16试试。
AWQ显存占用其实不大,问题大概率在max-num-seqs和prefill分配上,调完再看。
我之前也踩过类似的坑,--max-num-seqs确实挺关键的,默认值在并发高时会疯狂堆KV cache,你试着手动设成4或者8看看,能明显缓解显存压力。另外AWQ 4bit本身占用不大,瓶颈基本都在KV cache上,跟GPTQ关系不大,换8bit反而可能更吃显存。还有个小建议,可以调低--max-model-len到4096,内部demo一般用不了那么长上下文,省出来的显存够你多扛几个并发。
max-num-seqs确实是个关键,vLLM默认值偏保守,并发8时KV cache会按最大可能序列数预分配,你设到16或32试试,显存占用会平滑很多。另外AWQ 4bit本身没问题,Qwen2.5-7B量化后模型权重才4-5G,瓶颈肯定在KV cache和prefill内存上,GPTQ不一定更好。你可以先开个--enable-chunked-prefill,再把gpu-memory-utilization降到0.85,给KV cache留点余量,OOM概率会小很多。动态batch这块vLLM是自动的,但建议把max-num-batched-tokens也调一下,默认值可能不够你长上下文场景。
并发8就OOM确实不太正常,A100 80G跑4bit的7B模型理论余量很大。你试试把--max-num-seqs调低到4或2,同时--gpu-memory-utilization降到0.85,给KV cache留点缓冲,vLLM默认会按最大并发预分配显存,这个参数不调确实容易爆。另外AWQ和GPTQ在显存占用上差别不大,不用换量化,重点还是看vLLM的调度配置,你可以开--enable-prefix-caching试试,内部demo如果请求有公共前缀,能省不少缓存。
大概率不是量化本身的问题,AWQ 4bit在7B上模型权重也就占4-5G,你OOM基本是被KV cache吃掉的。--max-num-seqs确实很关键,默认值可能偏大,并发8的时候显存直接爆很正常,建议先调到2或4试试。另外--gpu-memory-utilization 0.9留的buffer有点少,动态batch下prefill和decode的显存波动比你想的大,可以降到0.85再观察。GPTQ和AWQ在显存占用上差别不大,换8bit反而更占,不如先调参。
说实话我觉得你方向有点偏了,AWQ 4bit在A100 80G上跑7B模型,模型权重撑死占个5-6G,真正吃显存的大头就是KV cache和临时激活值。你开gpu-memory-utilization 0.9但没限max-num-seqs,vLLM会按你给的显存预算去尽量塞更多的序列,并发一上来KV cache直接按序列长度和batch size线性膨胀,OOM太正常了。我之前跑类似的模型,max-num-seqs设成4到6,配合max-model-len 4096,压测到16并发都很稳,你试试把这两个参数压下来,别让vLLM自己放飞。至于GPTQ或者8bit,其实在7B这种规模上跟AWQ的显存差距没那么大,主要瓶颈还是调度策略,量化格式反而不是关键。另外你日志里有没有看具体是哪个tensor爆的?有时候是beam search或者采样参数开太大导致中间buffer炸了,不一定全是KV cache的锅。建议你先用vLLM的--enable-chunked-prefill试试,这个能显著降低长prompt场景下的瞬时显存峰值。还有个小坑,A100 80G不差这点显存,但如果你开了多进程或者有别的任务占显存,0.9利用率实际可用空间会缩水,最好用nvidia-smi确认下启动前空闲显存。总之先把max-num-seqs锁死,再观察KV cache监控项,大概率能解决。
max-num-seqs不调的话默认256,并发8直接爆很正常,先按并发数×2设一下试试。
建议把gpu-memory-utilization降到0.85,给CUDA留点余量,OOM多半是KV cache和激活值抢显存。
说实话你这个配置单路流畅但并发一高就炸,我第一反应就是max-num-seqs没调。vLLM默认值我记得是256,你想想看,8个并发请求进来,每个请求可能被拆成多个序列,KV cache的预分配是按这个上限来的,虽然gpu-memory-utilization设了0.9,但vLLM会先给模型权重留足空间,剩下的才给KV cache做动态池,一旦池子被撑爆就直接OOM,不会给你一点缓冲。
AWQ 4bit在Qwen2.5-7B上理论显存占用大概就6-7G,模型本身不是瓶颈,问题肯定出在序列长度和并发数的乘积上。你max-model-len设了8192,如果每个请求实际长度都很长,那8并发就是8*8192的KV cache在抢显存,这数值算下来确实容易爆。建议你先试着把max-num-seqs调到16或者32,配合max-num-batched-tokens限制一下单批总token数,比如4096或者2048,这样vLLM会强制做调度,而不是傻乎乎地按最大上限预留。
另外你提到的GPTQ或者8bit,我个人经验是AWQ在vLLM里支持得挺成熟了,换方案不一定能解决KV cache的问题,反而可能引入新兼容性问题。更推荐你先用--enable-chunked-prefill这个参数,它能把长请求的prefill阶段拆成小块,显存峰值会平滑很多,配合降低max-num-seqs效果立竿见影。动态batch这块vLLM本身是支持的,但你要确保没开--disable-chunked-prefill之类的反向开关。
最后补一句,A100 80G对于这个模型来说绰绰有余,你完全可以把gpu-memory-utilization降到0.8甚至0.75,留出更多余量给系统和其他进程,有时候卡死不是显存不够,而是显存碎片化或者驱动占用导致的。先调参数,大概率能解决,别急着换量化方案。
说实话你这个问题我上个月刚踩过,A100 80G跑7B AWQ按理说余量很大,问题八成不在量化本身,而在vLLM的默认调度策略上。--max-num-seqs确实很关键,默认值我记得是256,并发8的时候每个请求会抢占大量KV cache块,尤其是长上下文场景,显存直接就被预分配掏空了。你设了--max-model-len 8192但没限制批处理序列数,等于让vLLM按最坏情况给每个序列预留显存,8个请求就是8×8192的KV cache,不OOM才怪。建议试试把--max-num-seqs调到16或24,同时配合--max-num-batched-tokens限制单次推理的总token数,这样能让显存分配更平滑。另外AWQ和GPTQ在7B这个规模上显存差距其实很小,4bit和8bit倒是差不少,但你这情况换8bit只会更糟,优先调vLLM参数。还有个小坑,--gpu-memory-utilization 0.9在A100上不一定吃满,因为vLLM还会预留一部分给CUDA context和激活值,你可以试着降到0.85看会不会稳定点。动态batching这块vLLM确实有优化空间,但一般通过调整--max-num-seqs和--max-paddings就能解决,不用急着换后端。你先跑个压测矩阵,把--max-num-seqs从8到64挨个试一遍,观察显存曲线,应该能找到平衡点。
说实话你这个问题我上个月也踩过,A100 80G跑7B AWQ看着绰绰有余,但vLLM的显存分配逻辑比想象中激进。--gpu-memory-utilization 0.9不是直接把90%留给模型,而是把剩余空间全塞给KV cache,所以并发一高,预分配的KV块直接爆掉。你试下把--max-num-seqs降到4或者6,同时配--max-num-batched-tokens限制一下单batch的token总量,这个参数比max-model-len更直接控制显存峰值。另外AWQ本身没问题,GPTQ和它在这个规模上差距不大,别轻易换量化方案。
我自己的经验是,vLLM对动态batching的显存管理有点像“预分配+按需扩容”,但扩容有延迟,压测瞬间并发上来就来不及了。你可以在启动时加--enable-chunked-prefill,让长prompt分块处理,能明显降低瞬时显存峰值。还有个小技巧,把--block-size改成32而不是默认的16,KV cache碎片化会少一些。如果还不行,直接看下vLLM的日志里gpu_cache_engine初始化的KV cache大小,再对着nvidia-smi算一下模型本身占用,通常模型+激活值只占一半不到,剩下全是KV预分配。
最后提醒下,你--max-model-len 8192如果实际请求平均只有几百token,这个设置等于给每个seq预留了8K的KV空间,非常浪费。可以拿真实压测数据的平均长度去调这个值,比如改成2048或4096,显存压力瞬间小一半。动态batching确实吃显存,但vLLM官方文档里其实建议过,显存利用率0.9是为了跑满吞吐,你这种demo场景放到0.7反而更稳。
max-num-seqs不调的话默认值确实容易爆,先压到4试试,KV cache这块省下来立竿见影。
max-num-seqs确实得手动调,vLLM默认会按显存自动塞batch,并发一高KV cache直接爆掉。你A100 80G跑7B AWQ,模型本身才占5G左右,瓶颈肯定在KV cache分配上,建议先设个8或者16试试。另外量化这块AWQ挺稳的,GPTQ在vLLM上反而偶尔有精度抖动,没必要换。如果调完还OOM,可以看看是不是max-model-len设太长,8192对7B来说其实有点奢侈,砍到4096能省不少缓存。
max-num-seqs确实是关键,默认值在vLLM里会根据模型和显存自动算,但并发8时它可能把KV cache预分配得特别激进,你手动设个16或32试试,同时把gpu-memory-utilization降到0.85留点余量。AWQ 4bit本身占用不大,OOM大概率是KV cache峰值没控住,跟量化格式关系不大,GPTQ也不会有质变。另外动态batching时显存峰值会比单路高不少,建议压测时盯一下vllm的日志里seq长度分布,看是不是有超长请求把cache撑爆了。
说实话我觉得你大概率不是量化本身的问题,AWQ 4bit在A100上跑7B模型权重顶多占个10G出头,真正吃显存的大头就是KV cache和激活值。你设了--gpu-memory-utilization 0.9,vLLM会把这90%的显存全拿去做预分配,包括给KV cache预留空间,但问题在于它默认的--max-num-seqs是256,也就是说它按最多256个并发序列来预留KV cache,哪怕你实际只打到8并发,预留的buffer也不会缩回去,显存自然就被“虚占”满了。你可以试试把--max-num-seqs调到16或者32,再配合--max-model-len一起看,这样KV cache的预留会紧贴实际负载,OOM概率会低很多。
另外你提到动态batching,vLLM确实有continuous batching,但它对显存的管理还是比较粗放,尤其是当不同请求的prompt长度差异大时,它会按最大可能长度来预留空间,这也会加剧显存压力。我之前跑Qwen2.5-7B时遇到过类似情况,后来把--block-size从默认的16调到了32,同时开了--enable-chunked-prefill,对长prompt的并发场景改善挺明显。你可以先不换量化方案,把这两个参数加上再压测一轮,八成能解决。
至于GPTQ还是8bit,我觉得没必要急着换,AWQ在7B这个规模下精度和速度都够用,主要是vLLM对AWQ的kernel优化在某些场景下不如GPTQ成熟,但你这问题明显是显存规划逻辑导致的,不是量化格式的锅。真想排查的话,可以开--log-requests和--verbose看下每次请求分配的KV cache大小,或者用nvidia-smi dmon实时盯显存曲线,看到底是峰值瞬间爆掉还是缓慢累积。要是调完--max-num-seqs还不行,再考虑换GPTQ也不迟。
max-num-seqs确实挺关键的,默认值可能偏大,并发8的时候vLLM会尽量把多个请求塞进一个batch,KV cache峰值自然就爆了,建议先调到4或6试试。AWQ本身没问题,4bit下模型权重才5G左右,显存大头基本都在KV cache和激活上,跟GPTQ差别不大。另外你开了gpu-memory-utilization 0.9,但这只是给显存使用画了条线,实际分配还得看max-num-seqs和max-model-len的配合。还有个小坑,动态batching对长序列特别敏感,压测时如果请求长度不均匀,峰值可能比预期高很多,可以看看日志里实际处理的batch size是不是超过预期了。
之前跑7B也遇到过类似情况,--gpu-memory-utilization 0.9加上AWQ其实已经挺吃显存了,但这问题大概率不在量化本身,而是--max-num-seqs没限制,vLLM默认会尽量塞batch,KV cache瞬间就被撑爆。你试着手动设个--max-num-seqs 4或者8,同时把--max-model-len降到4096看看,压测时显存曲线应该会平缓很多。另外GPTQ和AWQ在显存占用上差距不大,不用急着换,8bit反而可能更占,先把动态batching的并发上限控住再说。
max-num-seqs确实是个关键参数,我之前的经验是并发上来后KV cache会按最大可能batch去预分配,你不限制它就会疯狂吃显存。AWQ 4bit本身占用不大,问题多半出在vLLM的调度策略上,试试把这个值调成4或8,同时把gpu-memory-utilization降到0.85给KV cache留点余量。另外你用的是动态batching的话,建议开一下continuous batching的显存池配置,不然OOM还是会反复出现。