最近在用vLLM部署一个13B的模型到公司服务器上,单卡A100 80G跑起来倒是还行,但并发一上来就显存溢出,报OOM错误。我试了GPTQ量化到4bit,精度有点下降但还能忍,结果显存占用还是跑满。问了同事,有人推荐用Flash Attention,有人建议上多卡张量并行,但我搞不清楚这些方案到底怎么落地。有没有大佬分享一下实际部署中压显存的成熟套路?或者有没有什么简单的trick能先顶住小流量?感谢!
部署开源大模型到生产环境,显存总不够用怎么办?
全部回复
共 161 条说实话,你这个场景我太熟了,13B单卡A100看着余量挺大,但并发一上来OOM几乎是必然的。GPTQ到4bit确实能压不少,但瓶颈往往不在权重,而在KV cache,尤其长上下文场景下每个请求的缓存累加起来非常恐怖。Flash Attention能省显存是真的,而且它是透明替换的,vLLM里直接开就行,建议先把这个加上,成本最低。多卡张量并行不是银弹,它主要是把权重和计算拆分到多卡,但每张卡还得存一份KV cache,如果你总显存合起来够用但单卡不够,那并行确实能解决问题,不过要注意通信开销,小流量下性价比反而不高。我个人建议先试试vLLM的continuous batching参数调优,把max_num_seqs和max_num_batched_tokens调小点,牺牲点吞吐换稳定,能先顶住小流量不崩。另外你GPTQ的group size可以调成128,精度损失和显存占用之间有个平衡点,别一上来就上最狠的4bit,有时候8bit加Flash Attention反而比4bit省心。还有个冷门trick,如果用的是HF的tokenizer,把padding side设成left,能让显存碎片少一点,这个我们线上验证过有点效果。最后想确认下,你并发上来的时候是单请求超长还是请求数爆炸?这两个场景的优化方向完全不一样,前者得搞kv cache量化,后者才靠调度策略。
说实话你这情况我太熟了,之前部署34B模型时也卡在OOM上,后来发现单纯堆量化不如把vLLM的gpu_memory_utilization调低点,给KV cache留出余量,小流量下至少能稳住不崩。Flash Attention确实能省不少显存,但记得要把模型重新跑一遍offline benchmark,不然精度和吞吐的平衡点不好找。多卡张量并行是真解法,不过你得先确认服务器有没有NVLINK,没有的话通信开销反而可能拖慢速度。临时顶一下的话,可以试试把max_num_seqs调小到16或者8,牺牲点并发换稳定,等流量上来再考虑扩卡吧。
Flash Attention和paged attention其实是vLLM默认就带了的,不用单独折腾,真正吃显存的大头是KV cache和激活值,建议先看下日志里具体哪块爆的。小流量顶一下的话,可以把max-num-seqs调小,比如8或16,再配合continuous batching的等待策略,能扛住一些。多卡张量并行对13B来说性价比一般,通信开销不小,真要上不如直接换更大显存的卡或者上量化+投机采样的组合。对了,GPTQ 4bit如果精度忍不了,试试AWQ,同bits下质量好点,显存占用差不多。
Flash Attention基本是必装的,能省不少显存,4bit加打不满的话再试试把max-seq-len调小点。
vLLM的OOM很多时候不是单卡显存不够,而是KV cache分配策略太保守了,试试调低gpu_memory_utilization到0.85,给推理留点缓冲。Flash Attention确实能省不少显存,主要是把attention的中间结果省掉了,落地也不难,直接换attention后端就行。多卡张量并行的话,13B用2张A100其实性价比不错,但要注意通信开销,小流量下可能还不如单卡调优来得快。另外我建议先看下是不是max_num_seqs设太高了,适当调低能明显缓解峰值压力。
建议直接上多卡张量并行,A100互联带宽够用,13B拆分后单卡负载小很多,顺便把max-num-seqs调低点。
vLLM 记得开 --enable-chunked-prefill,能省不少显存,特别是长 prompt 多的时候。Flash Attention 其实 vLLM 默认就带,你换多卡张量并行前,先看下是不是 max-num-seqs 设太高了,调小点能立刻缓解。小流量顶住的话,开 --max-num-batched-tokens 限制一下批量大小,比一味量化实在。
vLLM本身就能开多卡张量并行啊,你设个tensor-parallel-size=2,两张A100当一张用,代码基本不用改,先试试这个最实在。Flash Attention是跟显存优化无关,主要省的是计算和带宽,别指望它解决OOM。如果你愿意折腾,其实可以试试把KV Cache的分配策略调一下,vLLM里有个gpu_memory_utilization参数,别默认留太多余量。另外小流量的话,把max-num-seqs调低,比如8或16,能明显减少峰值占用,先顶着用。
Flash Attention和tensor parallel确实是两个方向,前者能省显存带宽但OOM问题不一定根治,后者把权重拆到多卡上才是硬道理。你如果只是小流量顶一下,可以先试试把vLLM的gpu_memory_utilization调到0.9,再把max_num_seqs调小,能扛住几个并发。另外GPTQ 4bit其实可以用AWQ替代,同精度下显存占用还能再低一点,不过要重新量化。大流量还是尽早规划多卡吧,单卡80G跑13B本来就很极限。
这个我踩过坑,单卡A100跑13B并发一高就是会爆。可以先看下是不是KV cache占太多,vLLM里把max_model_len调短点,比如从默认调到2048,能省出不少显存。Flash Attention主要是省attention那块的显存和加速,但对整体OOM帮助有限,不如直接上2卡tensor parallel,vLLM里设个tensor_parallel_size=2就行,代码基本不用改。如果暂时只有单卡,试试把并发请求排队,用pipeline并行或者干脆限流。
我建议你先别纠结量化精度,把vLLM的版本升到最新,它现在支持PagedAttention,能动态管理KV cache,比老版本省很多显存。我上次用13B模型,单卡80G
先上张量并行把单卡压力摊开,再开前缀缓存,小流量能顶一阵。Flash Attention对长上下文提升明显,但OOM主因还是并发显存分配,试试vLLM的continuous batching调低max_num_seqs。
说实话你这个问题我太有共鸣了,单卡A100 80G看着挺大,但vLLM的KV cache一吃起来,13B真hold不住多少并发。GPTQ 4bit降精度那点损失其实还好,但你得注意它省的是权重显存,激活和KV cache才是并发上去后的主要瓶颈,所以光量化不够。Flash Attention确实能省不少显存,而且vLLM本身就内置了,你只要确保启动参数里开了那个开关就行,实测对长序列效果特别明显,但别指望它能单独救你于水火。多卡张量并行是正道,但落地的时候模型并行切分逻辑和通信开销得调,你如果只有一台机器且目标并发不高,可以先试试pipeline parallel,配置起来比TP简单不少。还有个特别土的trick,就是限制单请求的最大生成长度,或者把max_num_seqs调小,配合vLLM的continuous batching,小流量下能明显减少OOM概率,代价就是吞吐上限低点。另外你检查过PagedAttention的KV cache预分配策略没,有时候实际占用的显存比算出来的理论值大很多,调一下gpu_memory_utilization到0.85左右给足预留空间,别默认值跑到底。最后如果预算允许,上两张A100做TP2,13B模型基本能撑住几十路并发,比我之前用单卡4090折腾量化强太多了,这钱花得值。
说实话你这情况我太懂了,之前我部署7B模型的时候也差点被OOM逼疯。Flash Attention和tensor parallel不是二选一,建议先上vLLM自带的--tensor-parallel-size 2把负载拆到两张卡上,A100 80G跑13B其实单卡算力是够的,瓶颈主要在KV cache上。你试过把--max-num-seqs调小吗?比如从默认的256降到32,并发请求排队而不是同时挤进显存,小流量场景下能立竿见影。GPTQ 4bit精度掉得厉害的话,试试AWQ或者把--quantization-format换成gptq_marlin,有时候同样的4bit推理框架不同,显存能差出10%-15%。另外查一下--gpu-memory-utilization,默认是0.9,你可以手动设成0.95让vLLM更激进地预分配显存,但别超过0.97容易崩。还有个trick,把--max-model-len从默认的4096缩到2048,如果你的业务prompt+输出没那么长,能省下大量KV cache空间。多卡张量并行虽然能摊薄显存,但要小心卡间通信开销,小流量下反而可能变慢,不如先把单卡的调度参数调优。最后建议你开一下--enable-chunked-prefill,长prompt会被切片处理,峰值显存能压下来不少,这功能在vLLM 0.4版本之后已经挺稳了。
试试把max-num-seqs调小点,配合continuous batching,小流量下能明显缓解OOM。
说实话你这个问题我之前也踩过坑,vLLM本身对显存管理已经算激进了,但13B上并发确实容易爆。我建议你先别急着上多卡,把max-num-seqs调小一点,比如从256降到64,再配合gpu-memory-utilization设到0.9,小流量场景基本能撑住。Flash Attention确实能省不少显存,而且对精度没影响,你可以直接换掉默认的attention后端试试。如果这还不行,那就只能上张量并行,但注意要加--tensor-parallel-size 2,并且把模型切分好,别一股脑全塞进去。
你这情况我太熟了,之前部署7B也卡在OOM上。Flash Attention能省不少显存,而且vLLM本身就支持,开个参数就行,可以先试试这个。多卡张量并行是治本的路子,但得改模型加载方式,建议直接看官方文档的示例代码,别自己瞎调。另外小流量顶一下的话,可以把max_num_seqs调小点,或者开个continuous batching,虽然吞吐会降但至少不崩。
vLLM这块我踩过不少坑,说下我的经验吧。你这个情况其实挺典型的,单卡80G跑13B本来就不宽裕,并发一上来OOM很正常,GPTQ 4bit能压到50G左右但一旦加长上下文和并发照样爆。我觉得你可以先看看是不是vLLM的KV cache没调好,默认会预分配很大比例显存,试试--gpu-memory-utilization调到0.85以下,再把--max-num-seqs调小点,比如8或者16,这样能先稳住小流量场景。Flash Attention确实能省不少显存,它主要是优化了attention的存储复杂度,从O(n²)降到O(n),vLLM里直接--enable-flash-attn就能开,基本无损,建议你优先试试这个。多卡张量并行是治本的办法,但落地起来麻烦一点,你得把模型切到多张卡上,vLLM里用--tensor-parallel-size 2就行,不过得注意你的服务器是不是NVLink互联,如果是PCIe的话通信开销会吃掉不少性能。还有一个trick是换更小的模型,比如用13B的量化版再加个小的embedding模型,或者直接降级到7B,很多场景下效果差不了太多但显存能省一半。另外你可以试试PagedAttention的v2,vLLM新版本里已经默认开了,它能把显存碎片利用起来,之前我遇到过类似问题升级完就好了。要是还不行,就把请求排队吧,用vLLM的--max-num-seqs和调度策略配合,宁可牺牲点吞吐也别让服务挂掉,生产环境稳定比什么优化都重要。
试试PagedAttention+抢占式调度,vLLM自带这功能,把max-num-seqs调小点能顶一阵。
张量并行其实没你想的那么复杂,两张卡设个tensor-parallel-size=2就行,但记得把KV cache也分均衡了。
Flash Attention确实是刚需,能省不少显存而且对精度没影响,建议先把这个加上。多卡张量并行的话,vLLM里配置tensor-parallel-size就行,但得注意A100的NVLink带宽,跨机走以太网的话性能会打折扣。另外小流量顶一下的话,可以调低max-num-seqs限制并发数,或者开个swap space让部分KV cache落盘,代价是延迟会涨。还有个取巧的办法,用AWQ替代GPTQ,同是4bit但校准后精度保留更好,显存占用差不多。
你这情况我太熟了,上个月刚帮团队调过类似的。4bit量化加vLLM其实有个坑,就是你得确认下是不是真的把KV cache也量化了,很多情况下只量化权重,显存大头反而在缓存上。Flash Attention确实有用,但vLLM新版本基本默认集成了,你要是老版本不如先升级试试,比手动改代码省心。多卡张量并行不是银弹,13B模型上2卡A100,通信开销有时候能把收益吃掉一半,除非你并发真的很高,否则不如先把max-num-seqs调小,vLLM里这个参数经常被人忽略,默认值对13B来说太激进了。另外可以看看PagedAttention的block大小,调小一点对碎片化显存友好很多,代价是吞吐略降,但至少不OOM。还有个野路子,如果只是顶小流量,可以把模型拆成半精度加载,然后强制用CPU offload部分层,慢是慢点,但能扛住突发请求。最后建议你开个NVIDIA的MPS,限制每个进程的显存配额,防止单个请求把显存全占了。
试试开vLLM的continuous batching和PagedAttention,小流量能撑住,大并发再上多卡张量并行。