最近在用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确实关键,调小点试试,另外换GPTQ不一定比AWQ省显存。
这问题我踩过一模一样的坑,先别急着换量化方案。AWQ 4bit在7B上模型权重也就占4-5G,你80G卡根本不可能因为权重OOM,罪魁祸首几乎肯定是KV cache和max-num-seqs的默认值。vLLM默认会按并发请求数动态分配KV cache,如果你不限制max-num-seqs,它可能为了追求吞吐把整块显存都预留给KV cache,但A100的80G在8192长度下每个seq的KV cache开销比你想象的大得多,8路并发直接爆很正常。
我建议你先用--max-num-seqs 4甚至2压测看看,同时把--gpu-memory-utilization降到0.7左右,给PyTorch和CUDA context留点余量,别卡在0.9那么极限。另外你提到的动态batching问题,vLLM确实会做continuous batching,但并发高时如果每个请求的prompt长度差异大,它会优先填充短的,导致KV cache碎片化,这个也会加剧显存压力。
至于换GPTQ或者8bit,我个人觉得没必要,AWQ在推理速度上比GPTQ有优势,而且你这个case明显是配置问题不是量化精度问题。我建议你先跑通max-num-seqs=4,然后逐步往上加,同时盯着nvidia-smi里“bar1 memory”和“context”占用,你会发现KV cache增长曲线很陡。还有个骚操作,可以试试--enable-prefix-caching,如果demo的请求有公共前缀,能省不少cache。最后,如果你实在不想调参,直接上FP16不加量化,7B权重也就14G,80G卡照样能撑住高并发,量化在A100上反而是负优化。
max-num-seqs确实是个关键参数,默认值可能偏大,并发8时每个sequence抢的KV cache空间会指数级膨胀,建议先调到16或32试试。另外AWQ 4bit本身没问题,但vLLM对AWQ的KV cache复用不如GPTQ成熟,你查下是不是显存碎片化导致的,可以试着加--enable-chunked-prefill。我之前用7B跑类似压测,gpu-memory-utilization太高反而会触发分配失败,降到0.85再配合max-num-seqs限制,OOM就少很多。动态batching这块你可以开个--max-prefill-tokens看看,但主要还是先把seq数和utilization调平衡。
你这情况我遇到过类似的,max-num-seqs确实得手动调,默认值在并发上来时会让KV cache疯涨,先把它压到16或8试试,比纠结量化位宽更直接。AWQ 4bit在7B上模型权重也就4G多,显存大头全在动态序列上,所以跟GPTQ关系不大。另外你gpu-memory-utilization开到0.9,建议留点余量,0.85配合显式限制seq数会更稳。动态batching本身没问题,但vLLM对长序列的预分配很保守,你max-model-len设8192但实际请求没那么长的话,试试用--max-num-batched-tokens限制总token数,能明显缓解OOM。
max-num-seqs确实得手动调,8并发直接爆显存大概率是它没限住。AWQ本身没问题,先把这个压到4试试。
看到你说KV cache占得凶,我觉得--max-num-seqs确实是个关键点,vLLM默认会按并发动态分配KV cache,不限制的话8并发直接吃满很正常,可以先设个4试试。AWQ 4bit本身没问题,7B模型权重也就5-6G,问题大概率出在预分配上,--gpu-memory-utilization 0.9再配个--max-num-seqs应该能压住。另外如果只做demo,其实可以试试把--max-model-len降到4096,短序列下KV cache压力会小很多。GPTQ或者8bit倒没必要换,先调参数看看效果吧。
这题我刚好踩过,--max-num-seqs确实是个隐藏大坑,默认值在vLLM里会根据模型和显存自动算,但并发上来以后每个seq的KV cache会动态增长,A100 80G看着大,实际被block管理吃掉的内存比你想的多。AWQ 4bit本身没毛病,模型权重只占几个G,问题几乎全在KV cache和prefill阶段的内存峰值上,你试试把--max-num-seqs手动压到4甚至2,同时加--enable-chunked-prefill,能把峰值打散很多。另外你设了--gpu-memory-utilization 0.9,但vLLM会预分配这部分显存给KV cache池,如果并发骤增时pool不够用,它不会动态扩展而是直接OOM,所以不如降到0.8留点余量。GPTQ和AWQ在这类场景下显存差异不大,换8bit反而更吃显存,别折腾量化格式了。我怀疑你压测时是不是有长prompt混在里面?短query和长文档混合请求时,prefill阶段峰值能冲到2-3倍,可以试试--max-prefill-tokens限制一下。最后建议你开vLLM的--use-v2-block-manager,新版这玩意儿对显存碎片处理好了不少,我这边同配置直接稳住了20并发。
max-num-seqs确实得手动调一下,默认值在并发上来时会疯狂塞请求进batch,KV cache直接爆掉,8并发配8192长度肯定扛不住,试试压到4或者8配合gpu-memory-utilization 0.85看看。AWQ本身显存占用比GPTQ略高一点,但7B模型量化后差距不大,问题大概率还是出在batch调度上,不是量化格式的锅。另外你日志里没贴vLLM版本,新版对动态batch的显存预留做了优化,升级到最新版可能也有帮助。
这题我熟,之前用vLLM跑Yi-34B也踩过类似的坑。--max-num-seqs确实很关键,默认值在并发上来时会把KV cache撑爆,建议先按并发数×2来设,再配合--max-model-len一起看。AWQ本身没问题,但4bit省下的显存远没你想象的多,大头还是在KV cache上。另外动态batching的开关(--enable-chunked-prefill)对突发流量也有影响,你可以试试关掉或者调整--max-num-batched-tokens,有时候反而更稳。
max-num-seqs确实得手动调,默认8并发直接吃爆KV cache,设成4试试。
max-num-seqs确实关键,默认值太大并发一高直接爆,调成4试试。另外AWQ吃显存比GPTQ略高,但你这配置8并发不该OOM。
max-num-seqs确实得手动调,8并发对7B来说有点猛,先降到4试试。AWQ本身没问题,你这大概率是KV cache爆了。
这问题我上周刚踩过,--max-num-seqs确实得盯一下,默认值在并发高时会让KV cache暴涨,尤其是长上下文场景。建议先把它压到4试试,再配合--max-model-len看显存曲线,大概率能稳住。AWQ本身不是主因,4bit在7B上撑8并发应该够,但vLLM的continuous batching对显存碎片挺敏感,如果还不行可以试试把--gpu-memory-utilization降到0.85给缓存留点余量。另外你日志里有没有paged attention的警告?我之前就是没开--enable-prefix-caching导致重复计算占显存,开完直接降了30%。
max-num-seqs不调的话默认会吃满显存,先限到4试试,比纠结量化格式管用。
说实话你这个问题我上周刚踩过一模一样的坑,A100 80G跑7B AWQ按理说余量很大,但并发一上来就OOM基本跟量化位宽关系不大,核心还是vLLM的调度参数没卡住。--max-num-seqs确实很关键,默认值好像是256,如果你不限制,vLLM会按最大并发去预分配KV cache,哪怕实际请求没那么多,显存也先被预留了。建议先把它压到16或者32试试,同时把--max-model-len降到4096看看,因为8192的KV cache占用是平方级增长的,对7B模型来说实际业务用不到那么长上下文的话纯属浪费。另外你开了--gpu-memory-utilization 0.9没问题,但vLLM有个特性是它会尽量把剩下的显存全吃进KV cache的预留池,所以即使你设了0.9,它也会在启动时就把那90%显存“锁定”,并发一高反而容易触发碎片化。AWQ本身对显存优化已经不错了,换GPTQ或8bit在KV cache占用上不会有本质区别,别折腾那个。还有个容易忽略的点,vLLM的动态batching对请求长度差异很敏感,如果压测时发的prompt长度参差不齐,它会为最长的那批预留空间,导致短请求也占着大块KV cache。你可以试试在压测脚本里固定输入长度,或者开--enable-prefix-caching,但我觉得最直接的办法还是把--max-num-seqs和--max-model-len都调小,跑一轮看nvidia-smi里KV cache的峰值,基本就能定位了。
max-num-seqs确实是关键,vLLM默认会按模型和显存猜一个值,但并发一高它可能把KV cache预分配撑爆,你可以先试着把它调到4或8,配合gpu-memory-utilization降到0.85看看。AWQ本身没问题,7B 4bit模型权重也就5G左右,OOM基本都出在KV cache上,不是模型本体。另外动态batching肯定有影响,vLLM会尽量塞满batch,但你要是不调max-num-seqs,它容易高估可用显存。我上次跑类似配置,是把max-num-seqs锁死+max-model-len降到4096才稳的,你可以先按这个思路试。
说真的,你这种情况我太熟了,之前用vLLM跑Yi-34B的时候也是这个鬼样子,单发稳如老狗,一上并发直接炸。--max-num-seqs确实是个大坑,默认值我记得是256,它直接决定了vLLM一次性会往显存里塞多少条序列的KV cache,你并发8但每个请求如果还带点beam search或者多轮历史,实际序列数可能远超8,显存瞬间就被预分配掏空了。我建议你先把这个参数压到16或者32试试,同时把--max-model-len降到4096看看,很多时候不是模型权重占地方,是KV cache的预留机制太激进。另外AWQ和GPTQ在7B这个规模上显存差异真的不大,别折腾换量化了,纯属浪费时间。更关键的是你--gpu-memory-utilization 0.9其实留了10%给碎片和CUDA context,但压测时如果vLLM的调度器判断显存不够,它不会自动等,而是直接尝试分配然后OOM。你还可以试试开--enable-prefix-caching,如果内部demo的请求有共享前缀,能省不少KV cache。最后一个骚操作是换用最新版vLLM,老版本对连续批次的显存管理很傻,新版改了调度策略,同样参数下能多扛一倍并发。你要是还不行,就把--max-num-batched-tokens显式调小,强制它每次迭代少算点token,牺牲一点吞吐换稳定,demo够用了。
--max-num-seqs确实得手动调一下,vLLM默认会按显存余量动态分配,但并发一高它容易把KV cache撑爆,我遇到过类似情况,设成8或者16能明显缓解。AWQ本身没问题,4bit下模型权重才5G不到,撑爆显存的肯定不是权重。另外你gpu-memory-utilization 0.9留给KV cache的比例其实偏激进,可以试试0.85,同时把--max-model-len降到4096看看,内部demo用不到那么长上下文。动态batching在vLLM里是默认开的,但并发高时调度策略对显存峰值影响很大,建议也看看--enable-prefix-caching是不是没开,开了能省不少重复计算。
说实话我觉得你方向有点偏了,AWQ 4bit在A100上模型权重也就5G出头,根本不是瓶颈。KV cache才是大头,你开了gpu-memory-utilization 0.9等于把剩下75G全留给KV cache了,但vLLM默认max-num-seqs是256,8并发下每个seq都能分到巨大的cache空间,反而容易一次性撑爆。我之前调Qwen2.5-7B时把max-num-seqs压到32,同时设了max-num-batched-tokens,OOM立刻就好转了,你可以先试试这个组合。
另外你这场景其实不用上GPTQ,AWQ在7B上跟GPTQ差距很小,换成8bit反而更占显存。真正要注意的是vLLM的动态batching逻辑,它会在并发高时把多个sequence拼到一个batch里,如果max-num-seqs不限制,KV cache会按最大可能分配,而不是按实际需求。我建议你把gpu-memory-utilization降到0.85,再显式指定max-num-seqs=16,然后观察nvidia-smi里的显存曲线,大概率能稳住。
还有个坑是--max-model-len 8192,如果你实际输入长度远小于这个值,KV cache还是按8192预留的,非常浪费。可以试试用--max-num-batched-tokens限制每次forward的总token数,比如设成4096,这样并发高时vLLM会排队而不是硬塞。我自己的经验是,这类demo场景根本不用追求满并发,A100跑7B,8并发已经很有余量了,大概率是你参数没咬合上。
说实话你这配置看着挺合理,但问题大概率不是量化本身,而是vLLM的调度策略。AWQ 4bit下模型权重也就4-5G,真正吃显存的是KV cache的pre-alloc,你设了gpu-memory-utilization 0.9,它就会按这个比例去预留显存,但并发一高,每个seq的KV cache是动态增长的,如果max-num-seqs没限制,vLLM会尽量多塞请求进来,结果就是预分配不够用直接爆掉。
我之前调Qwen2.5-14B也遇到过一模一样的情况,后来把max-num-seqs手动设成16或者32,同时配合max-model-len和block-size一起调,明显稳很多。你这个7B模型,单卡A100其实余量很大,试试把gpu-memory-utilization降到0.8,留点显存给CUDA context和碎片,再显式设--max-num-seqs 8或者16,应该能扛住。
另外你说AWQ和GPTQ,其实这俩在vLLM里的显存表现差不太多,8bit反而更占,没必要折腾。动态batching确实是vLLM的强项,但你要理解它默认是“能收就收”,不会提前给你做backpressure,所以并发控制得靠参数硬卡。
还有个坑,nvidia-smi看到的显存占用高不一定是真的满,有时候是vLLM的memory pool提前占用了,你可以在日志里看下“GPU KV cache size”和“max_num_seqs”这两个字段,确认一下实际瓶颈。如果压测时还OOM,试试加--enforce-eager,虽然慢一点但能省掉CUDA graph的显存开销,排查问题很好用。