最近在搞一个内部知识库问答,用的Qwen2.5-7B,单卡A100 40G。刚开始fp16直接爆显存,后来试了AWQ 4bit量化,能加载进去了,但推理时并发一上来(大概4-5个请求)还是会偶发OOM。已经开了vLLM,也设了max-num-seqs,感觉还是不太稳。有没有朋友遇到过类似情况?是模型本身太大还是我的服务配置有坑?另外系统提示词和history轮次多了之后显存增长也挺明显,有没有什么清理机制或者更省显存的attention优化方案?求实战经验,不想再盲调参数了,感谢!
大模型本地部署显存爆了,量化也试了还是OOM,求指点
全部回复
共 92 条这配置跑7B其实挺极限的,A100 40G单卡推理并发就是容易出幺蛾子。试试把max-num-seqs降到2,然后开一下vLLM的continuous batching,另外prompt的KV cache复用对多轮对话省显存很关键,可以查下有没有开chunked prefill。至于history,建议做个滑动窗口,超过10轮就截断或摘要,别全塞进去。
vLLM的KV cache显存预留是动态的,4-5并发确实会顶到天花板,调低gpu-memory-utilization到0.85左右试试。另外AWQ虽然省了权重,但激活值和KV cache还是吃fp16,可以试试Qwen自带的GQA配合flash-attention,能压不少。系统提示词尽量精简,每多1k token,KV cache就要多占约2MB×层数。
我上次用7B也这情况,后来发现是vLLM的preempt模式没调好,改成swap模式后并发稳了很多。history轮次多的话,可以自己写个中间层做语义压缩,只保留最近3轮完整对话+前面内容的摘要,显存涨速能慢一半。另外你确认下是不是max-model-len设太大了,默认可能留了8k的余量,实际用不到的。
遇到过类似的,Qwen2.5-7B在40G上跑并发确实紧,但你这情况更像是kv cache没控住,max-num-seqs调低到2试试,再配合--gpu-memory-utilization设个0.9。history轮次那个坑我懂,可以在vLLM里开prompt logits缓存,或者自己写个滑动窗口把老对话截断掉,不然吃显存跟滚雪球一样。另外AWQ虽然省了权重,但激活内存没降,可以看看flash attention版本是不是没生效,有时候vLLM默认没开对后端。
试试把max-num-seqs调到2,再加个continuous batching的版本更新,应该能稳不少。
history那部分用滚动窗口截断吧,别全塞进去,KV cache才是大头。
试试把KV cache的quantization打开,再给history轮次设个硬上限,并发调低点基本能稳。
我也踩过类似的坑,7B模型配40G卡其实不算小马拉大车,但并发一多就露馅。你试试把KV cache的量化打开,vLLM里有个kv_cache_dtype=fp8_e5m2的参数,能省不少显存,而且对精度影响很小。另外那个history轮次增长的问题,建议搞个滑动窗口截断,别把全部上下文都塞进去,系统提示词也可以固定长度裁掉最老的部分。我之前用transformers的flash attention 2也有效果,但vLLM里得确认版本支持。还有个小技巧,max-num-seqs别只调数字,配合gpu_memory_utilization一起看,留点余量给峰值波动,我当时设到0.9才稳。
这问题我太熟了,之前用7B模型跑内部工具时也卡在这。你降到4bit还能OOM,大概率不是模型权重的问题,而是KV cache在作怪,尤其你提到history轮次多的时候显存涨得飞快,基本就是它了。vLLM的max-num-seqs只是限制并发序列数,但每个序列的KV cache还是会按最大长度预分配,建议把max-model-len调小点,比如限制到2048或4096,能省出不少空间。另外开一下enable_prefix_caching,如果多个人问相似问题能复用公共前缀的KV,效果很明显。系统提示词如果特别长,可以试试固定成静态张量,别每次都重新算。要是还不行,考虑换MHA为GQA的模型,比如Qwen2.5-7B-Instruct本身支持GQA,但你要确认vLLM版本有没有正确启用,有些老版本默认没开。最后实在不行就上多卡流水线并行,或者用offload到CPU,虽然慢点但至少不崩。
并发OOM八成是KV Cache爆了,试试把max-num-seqs砍到2再加个--swap-space,history轮次用截断别全塞进去。
试试把max-num-seqs调到2,再开下vLLM的continuous batching,并发OOM能缓解不少。
这问题我也踩过坑,A100 40G跑7B按理说余量挺大,但你开vLLM的时候得注意它默认会预留一部分显存做KV cache和CUDA context,加上并发请求的prefill阶段峰值很容易瞬间冲高。我试过把gpu-memory-utilization调到0.85,然后max-num-batched-tokens卡在4096,同时把--enable-prefix-caching打开,能缓解不少,你可以先看看这几个参数的实际占用曲线再调。至于history轮次和系统提示词导致的显存增长,本质上是KV cache在累积,vLLM里有个--max-model-len可以限制总长度,但更有效的是自己写个简单的滑动窗口,比如只保留最近5轮对话,或者把系统提示词压缩成固定长度的摘要,别每次都拼全量。另外AWQ 4bit虽然省了模型权重,但attention部分还是吃显存,试试MHA换成GQA的变体(如果模型支持),或者用flash-attention 2的varlen接口,能省不少临时张量。我最后是换成了Qwen2.5-7B-instruct的GGUF Q4_K_M,配合llama.cpp的server模式,并发10个都没再OOM,就是吞吐比vLLM低一些,但胜在稳定,你可以权衡下。
说实话你这情况我太熟了,之前用7B模型做rag也踩过一模一样的坑。fp16爆显存不奇怪,但AWQ量化后还OOM,大概率不是模型体积的问题,而是kv cache在作祟——你试过把max-num-seqs调低到2或者3吗?并发4-5个请求对7B来说其实不算多,但vLLM默认会为每个请求预留大量显存做预分配,这个参数没调好很容易触发偶发溢出。另外你说history轮次多了显存涨得明显,这基本就是kv cache线性增长的典型表现,建议在服务端做滑动窗口截断,比如只保留最近5轮对话,或者用H2O之类的streaming attention方案,能砍掉一半以上的cache占用。还有个野路子是改用GPTQ量化配合--max-model-len限制输入长度,实测比AWQ在长上下文场景更省显存,但推理速度会慢一丢丢。对了,你vLLM版本是多少?1.5.0之后有个--enable-chunked-prefill选项,专门处理这种高并发下的显存碎片问题,试试看有没有改善。
这问题我也踩过,7B在40G上fp16理论够但KV cache和中间激活才是大头,尤其长上下文并发直接爆炸。建议把max-model-len砍到4096或2048,配合vLLM的enable-prefix-caching能省不少重复计算。另外开个--kv-transfer-config试试,或者改用pagedattention的块大小调低点,我这边4bit下用这些设置能扛住8并发不OOM。history轮次多就做个滑动窗口截断,别全塞进去。
这问题我太熟了,之前搞32B模型的时候被OOM折磨了一周。你40G跑7B按理说余量很大,我怀疑瓶颈不在模型权重,而是KV cache和显存碎片。vLLM的max-num-seqs设了之后还得看gpu-memory-utilization,建议直接锁到0.85,给连续分配留足空间。另外系统提示词和history这块,强烈建议你做个滑动窗口,只保留最近几轮对话,或者用LLM先对旧消息做摘要再拼进去,不然KV cache翻倍增长是必然的。还有个偏方,把AWQ的group size从128调成32,显存占用会再降一截,虽然速度慢点。对了,你确认过是不是PagedAttention没生效?有时候版本问题会导致它默默降级成普通attention,那并发必炸。最后问下,你的并发压力测试是真实业务还是脚本压的?如果是脚本,注意把输入长度也随机化,不然缓存命中率会给你假象。