最近在搞一个内部工具的对话接口,用VLLM部署了Qwen2.5 7B,单次调用挺流畅的,但并发一上到10个请求左右就开始频繁OOM,直接Kill进程。我看配置里设了max_num_seqs=256,gpu_memory_utilization也调到了0.8,还是顶不住。是不是我模型加载方式不对?还是需要换量化版本?或者得拆成多个副本?求有经验的老哥指点一下,预算有限暂时上不了A100,就一张3090。
VLLM部署Qwen2.5 7B,并发一高就OOM怎么办?
全部回复
共 160 条说真的max_num_seqs=256在3090上跑7B有点太激进了,这参数不是越高越好,显存得按实际峰值来算。我之前用24G卡跑7B,max_num_seqs调成32都偶尔会爆,后来直接砍到16才稳。gpu_memory_utilization调到0.8其实已经很低了,但你要注意vllm的prefill和decode阶段显存占用差很多,并发高的时候prefill阶段会瞬间吃满。建议你先盯着nvidia-smi看下OOM前显存到底涨到多少,如果已经接近24G,那大概率不是加载方式的问题,纯粹是显存物理不够。量化的话AWQ 4bit能省一半左右显存,但3090跑7B其实没必要上量化,除非你打算把max_num_seqs拉回256。我个人更建议拆两个副本,每个副本显存控制在11G左右,再用nginx或者vllm自带的router做负载均衡,这样单副本挂了也不影响另一个,比单卡硬扛强多了。另外你检查下是不是开了长上下文,Qwen2.5 7B默认8K,如果跑到32K,显存占用直接翻几倍,这个很多人容易忽略。
3090就24G显存,跑7B还开256的max_num_seqs,这配置本身就挺吃紧的,OOM不奇怪。建议先把max_num_seqs降到32或者64试试,vLLM的prefill阶段显存峰值很夸张,并发一高就爆。另外gpu_memory_utilization调到0.85以上,再把KV cache的量化打开(比如fp8),能省不少。如果还不行,就上AWQ或者GPTQ的4bit量化版,效果基本不掉,显存能省一半。多副本就别想了,3090单卡撑不住,不如直接限制并发数,把请求排队处理。
3090显存就24G,max_num_seqs调这么高必炸,先砍到32试试,再不行上AWQ量化。
3090就24G显存,跑7B满血版本来就很极限,max_num_seqs改成256反而是负担,试下砍到32或者64,再配合vllm的continuous batching,OOM概率会小很多。量化的话建议直接上AWQ或者GPTQ的4bit,显存占用直接砍半,单卡并发能翻一倍,效果损失基本感知不到。
另外gpu_memory_utilization别死磕0.8,留点显存给CUDA context和碎片,0.7左右更稳。如果还顶不住,就别硬撑单卡了,拆两个副本各占12G,用nginx做负载均衡,比调参省心。我之前就是这么干的,3090跑4bit的Qwen2.5 7B,并发30都没崩过。
说实话max_num_seqs设256在3090上有点太激进了,24G显存跑7B满血KV cache根本扛不住,试试压到32或者64,OOM概率会小很多。另外你这场景如果并发就10个左右,建议直接上AWQ或者GPTQ量化版,4bit精度下显存占用能砍一半,效果损失基本感知不到。真要拆多副本的话3090单卡也撑不起几个实例,反而更吃内存,不如先把gpu_memory_utilization降到0.6留点余量给KV cache,再把vllm的--swap-space调大点试试。
3090跑7B并发10个确实勉强,先试试把max_num_seqs砍到32,再加个--enable-prefix-caching。
3090上16G显存跑7B并发10个确实紧,max_num_seqs=256这个值设太大了,实际并发10的时候显存直接爆掉,建议先砍到32或者64试试。另外gpu_memory_utilization=0.8留给KV cache的余量不够,可以试着降到0.7,给推理留更多缓冲。量化的话AWQ或者GPTQ的4bit版本会好很多,我之前用同配置跑4bit能扛到20并发不炸。要是还不行就拆两个VLLM实例各占一半显存,用负载均衡分流,比单实例硬扛稳。
max_num_seqs调低到32试试,3090显存就24G,256并发纯属找死。
3090就16G显存,跑7B fp16权重都要占14G+,KV cache空间被压得很死,max_num_seqs=256纯属摆设。先把并发压到4-8试试,然后上AWQ或GPTQ的4bit量化,显存占用直接砍一半,KV cache才能腾出来。另外注意下VLLM版本,老版本对量化支持有坑,换个0.6以上的试试。多副本就别想了,单卡跑两个实例反而更吃显存。
3090跑7B并发10个确实吃力,先试下把max_num_seqs砍到32,再用AWQ量化能省不少显存。
你这配置单卡7B并发上限就那样,量化加限流双管齐下吧,拆副本反而更吃显存。
说实话max_num_seqs=256这个配置在3090上跑7B本身就是个矛盾,显存带宽和容量都扛不住这么高的并行度,vllm的调度器会疯狂把KV cache往显存里塞,OOM几乎是必然的。我自己的经验是3090上跑7B,max_num_seqs压到16到32之间才稳,gpu_memory_utilization给到0.85可以但得配合--swap-space,否则物理显存爆了之后vllm的显存管理反而会触发额外开销。你现在的瓶颈大概率不在模型权重,而是KV cache的峰值占用,建议先看下vllm启动日志里实际分配的KV cache大小,如果远小于模型权重占比,说明池子太小了。另外量化确实能缓解,AWQ或者GPTQ的4bit版本能把权重砍半,但KV cache还是原样,所以并发问题改善有限,除非你同时降max_num_seqs。拆副本的话,单张3090跑两个实例反而会互相抢显存,除非你能接受把batch size砍到极低,不然不如直接上vLLM的continuous batching配合--max-parallel-loading-workers试试。还有个坑是默认的preemption模式,如果没设--swap-space,OOM时vllm会直接杀进程而不是swap到CPU内存,这可能是你看到进程被Kill的直接原因,建议加上--swap-space=16看看。最后建议你实测一下单请求的显存占用和峰值,用nvidia-smi盯一下,先摸清楚到底是权重还是KV cache爆的,再决定动哪个参数。
3090显存就24G,跑7B还得同时扛KV cache,max_num_seqs=256这个值设太大了,并发一高KV cache直接爆掉,先砍到32或者64试试,应该能稳住。另外gpu_memory_utilization设0.8其实还有优化空间,可以试着再降一点,给KV cache留更多余量。真要上10并发的话,建议直接用AWQ或者GPTQ的4bit量化版,显存占用能少一半,基本就够用了。还有个土办法,vllm里开个--enable-prefix-caching,对聊天这种高频前缀场景帮助挺大的,先试试这几个再考虑拆副本。
说实话你这配置我太熟了,之前拿3090跑7B也是这个鬼样子。max_num_seqs=256在vLLM里其实是个上限,不是说你设了它就真能扛住那么多并发,关键还是看KV cache能不能塞进显存,OOM基本就是cache分配炸了。建议先把max_num_seqs砍到32或者64试试,同时把gpu_memory_utilization降到0.7左右,给CUDA context和碎片留点余地,很多时候0.8反而触发vLLM的激进预分配。另外你确认下是不是开了自动前缀缓存,如果输入里带大量重复的system prompt,这个功能会吃额外显存,关掉可能立竿见影。量化的话AWQ 4bit对3090挺友好,显存占用能砍一半多,但注意7B量化后质量下降在你这种内部工具上一般能忍,我实操下来AWQ比GPTQ在vLLM里更稳。至于拆多副本,单卡3090拆了也是分时复用,不如先把batch size压下来看实际吞吐,真不行再考虑加一张二手卡做张量并行。还有个坑是vLLM版本,老版本对7B的显存管理有bug,你升级到0.6.3以上再试,我上次就是更新版本后OOM频率直接降了八成。
说实话max_num_seqs=256在3090上跑7B有点过于激进了,这参数不是设得越高越好,它决定了显存里能同时缓存多少条序列的KV state,256条并发光KV cache就得吃好几个G。你实际并发才10个,但vllm会预分配满这个上限的显存,所以OOM大概率是预分配爆了而不是真到10个请求才爆。建议先把max_num_seqs降到32甚至16试试,同时把gpu_memory_utilization降到0.7以下,给torch和CUDA context留点余量,3090就24G,7B的FP16权重已经占14G了,剩下的空间真没你想的那么宽裕。
再一个,你确认下是不是用了默认的continuous batching策略,vllm对长上下文的显存占用是按最大长度预分配的,如果接口传的max_tokens设得很大,比如2048以上,那每个seq预留的空间会非常恐怖。可以试试把max_model_len限制到2048或者1024,代价是长对话会被截断,但内部工具一般够用。要是还不行,那就上AWQ或GPTQ的4bit量化版,7B量化后权重才4G左右,能腾出大量显存给KV cache,而且3090跑4bit推理速度损失很小,基本感知不到。
至于拆多副本,3090单卡真没必要,vllm本身就是为高并发设计的,拆了反而增加显存碎片和调度开销。另外检查下是不是没开--enable-prefix-caching,如果你们对话历史有重复前缀,这个能省不少显存。最后说句实在的,如果并发10个是常态,建议直接看下vllm的日志里具体是哪一步OOM,是预分配阶段还是运行中,有时候是paged attention的page size没调好,默认16可能不适合你的场景。先按这个思路调一下,大概率能撑住。
3090显存就24G,跑7B fp16权重都快占满了吧,你给KV cache留的空间本来就不多,max_num_seqs调256反而让显存碎片化更严重。建议先降到32或者64试试,另外开下--enable-prefix-caching,能省不少重复计算的显存。实在不行就换AWQ或者GPTQ的4bit量化版,显存占用能砍一半,单卡扛个二三十并发应该没问题。
3090跑7B并发10个确实勉强,max_num_seqs调小到32试试,OOM多半是显存碎片化。
量化成AWQ或GPTQ能省一半显存,你这场景够用了,实在不行就上2张卡切分。
3090也就24G显存,跑7B满血版本来回切换KV cache确实容易爆,max_num_seqs别拉那么高,先降到32试试,这参数不是越大越好,跟显存和请求长度直接挂钩。另外gpu_memory_utilization设0.8其实留给context的空间不多,建议把模型换成awq或gptq量化版,4bit下显存占用能砍一半,并发应该能翻倍。还有个野路子,vllm里开enable_prefix_caching,如果你们内部工具请求有重复前缀,能省不少显存。我之前用4090跑同款模型,并发20都没事,关键还是把seq长度和批大小调匹配了。
3090跑7B开256的max_num_seqs确实太激进了,先砍到32试试,另外换AWQ量化能省不少显存。
max_num_seqs调低点再开个--enable-prefix-caching,OOM基本能缓解,量化版本不急换。
3090也就24G显存,跑7B满血版本来回也就勉强塞下权重和KV cache,max_num_seqs调到256纯属给显存上刑,实际并发10个就会把KV cache撑爆,进程直接被OOM killer干掉很正常。你可以先把max_num_seqs降到16或者32试试,同时把gpu_memory_utilization调回0.9以上,给KV cache多留点空间,VLLM对这两个参数的组合很敏感,不是越大越好。另外建议直接上AWQ或者GPTQ的4bit量化版,7B量化后显存占用能砍一半,3090跑起来余量就大了,单卡并发20个问题不大,推理速度损失也基本感知不到。要是还想再压榨一下,可以把Qwen2.5的KV cache换成fp8或者int8,VLLM最新版支持kv_cache_dtype设置,能再省几个G。至于拆多副本,你这预算还不如先折腾量化,因为就算拆两个VLLM实例,每张卡还是同样的问题,除非上多卡推理,但3090没有NVLink,多卡通信开销反而会让你更难受。我这边之前用4090跑同模型,量化后max_num_seqs设64,并发20多稳定不炸,你可以照这个方向调调看。
一张3090跑7B还要扛10并发,OOM基本是必然的,不是加载方式的问题。max_num_seqs=256这个值在24G显存下太激进了,vLLM会为每个seq预留KV cache,实际能同时跑的远没这么多,建议先压到32-64试试,同时把gpu_memory_utilization降到0.7,留点余量给碎片和中间张量。
另外你测过单并发时的显存占用吗?如果接近22G,那说明模型本身已经吃满,并发一高KV cache直接撑爆。这种情况下不用纠结量化,AWQ或GPTQ的4bit能省一半显存,但3090跑7B的4bit精度损失其实可接受,内部工具完全够用,建议直接上AWQ版本,吞吐能提升不少。
如果量化后还是不行,那就得考虑拆分部署了,比如用ray起两个vLLM实例,每个实例限制max_num_seqs=16,前面挂个负载均衡。不过一张3090拆两个实例,每个显存只剩12G,7B量化后勉强能跑,但并发能力提升有限,不如先调参再决定。
还有个容易忽略的点,检查下vLLM版本,老版本对KV cache管理有bug,升到最新版有时候能解决莫名OOM。另外prompt长度是不是特别长?如果单条输入几千token,KV cache消耗会翻倍,建议限制max_model_len到2048或4096试试。
总之别一上来就加副本,先把max_num_seqs和量化组合调好,3090跑7B撑住10-20并发是可行的,但别指望它像A100那样稳定,内部工具偶尔降级也能理解。