最近在折腾本地部署,想用vLLM跑一个70B的模型(比如Llama 2 70B),手头是8张3090(24GB)。按道理8*24=192GB显存,应该够吧?但实际启动时老是OOM,查了资料发现可能跟张量并行和流水线并行的切分方式有关。我试了tensor-parallel-size=8,结果每张卡显存直接冲到22GB,推理速度也慢得离谱。想问下各位,这种情况是不是应该用pipeline-parallel配合tensor-parallel?或者量化后跑int8/4?还有,如果只用4张卡,是不是反而更稳?求具体参数参考,谢谢!
请教大佬们,8卡3090部署70B模型怎么切分才能不爆显存?
全部回复
共 137 条8卡全上tensor parallel=8确实容易撞墙,因为70B哪怕bf16光权重就要140G,加上KV cache和激活值很容易爆。你试试tensor parallel=4 + pipeline parallel=2,把KV cache比例调低点,应该能稳不少。int8量化是个逃不掉的选择,实测4卡TP=4跑int8大概16G/卡,速度比8卡bf16还快。另外注意vLLM的gpu_memory_utilization别开太满,0.85左右留点余量,不然调度时容易OOM。
TP=8通信开销太大,试试TP=4+PP=2,或者直接上INT4量化,8卡稳得很。
8卡全上TP=8通信开销太大,建议TP=4+PP=2,量化到int8基本稳了。
TP=8通信开销太大,试试TP=4+PP=2,配合AWQ量化,稳得很。
TP=8切了照样爆多半是显存碎片化,试试先量化到int4再开TP=8,速度能接受。
说实话你这情况我太熟了,当时我用8卡3090跑65B也是被OOM折磨了好几天。关键问题不在总显存,而在于KV cache和中间激活值,70B模型光是权重就要140GB,加上推理时的临时张量,tensor-parallel-size=8每张卡塞满22GB真不算意外。我的建议是别死磕纯TP,试试tensor-parallel-size=4加pipeline-parallel-size=2,这样每张卡的压力会小很多,而且通信开销也降下来了。另外量化几乎是必须的,int8权重能砍到70GB左右,这样就算TP=8也能留出不少余量给KV cache,吞吐会好看很多。至于只用4卡,如果跑纯离线推理确实更稳,但并发一上来就抓瞎了,我个人还是倾向8卡加量化。还有个小坑,vLLM的gpu-memory-utilization参数记得调到0.9以上,默认值保守得离谱,我之前就是栽在这上面。你试的时候注意看下日志里实际峰值显存,别光看nvidia-smi,有时候碎片化也会导致OOM。
8卡全上tensor parallel=8确实容易撞墙,因为all-to-all通信开销太大,3090的PCIe带宽扛不住。建议先用4卡tp=4加pp=2,显存占用会降到15G左右,速度反而比8卡快。另外int8量化基本无损,强烈建议开,显存能省三分之一。我自己的经验是70B用4卡tp=4最稳,8卡留给更大模型或者上offload才划算。
8卡3090跑70B其实卡在KV cache和中间激活值上,光看参数量没用。TP=8的话每张卡通信开销太大,尤其3090没有nvlink,跨PCIe传输直接拖垮吞吐。建议TP=4+PP=2,同时开--enable-chunked-prefill,把KV cache上限调低点。int8量化基本无损,能省不少显存,4卡方案更稳但得牺牲上下文长度,实测7B都容易爆,70B还是老老实实上量化吧。
8卡全上反而容易卡在通信瓶颈上,试试tp=4+pp=2,再开个int8量化,显存能压到16G左右。
我之前也踩过这个坑,8卡全上tensor parallel反而会因为通信开销太大把速度拖垮。建议试试tensor-parallel-size=4加pipeline-parallel-size=2,显存压力小很多,速度反而能上来。量化的话int8够用,但4bit得看模型支不支持,别硬上。只用4卡确实更稳,但24GB跑70B int4也悬,最好先量化再切。你当前跑的是原版fp16吧?要不先降到8bit看看峰值显存占用。
8卡3090跑70B其实tensor-parallel=8不是最优解,显存是够但通信开销太大,速度反而被拖垮。我建议你试试tensor-parallel=4加pipeline-parallel=2,这样每卡压力小很多,推理延迟也能接受。量化的话,int8是个不错的折中,显存能压到15G左右,4卡跑起来反而比8卡稳,因为卡间带宽瓶颈少一半。你vLLM版本更新到最新了吗?老版本对PP支持不太好,有时候明明没满显存也报OOM。
说实话8卡3090跑70B这个规模,瓶颈不在总显存,而在单卡容量和通信带宽。192GB看着够,但Llama 2 70B的权重本身就接近140GB,加上KV cache和激活值,tensor-parallel-size=8时每张卡要存完整的层权重切片,但3090的PCIe带宽和NVLink拓扑如果没优化好,反而会让通信开销吃掉推理速度,22GB显存其实已经接近危险线了。
我自己的经验是,纯tensor并行8卡容易踩通信瓶颈,尤其非NVLink互联的机器,建议试试tensor-parallel-size=4 + pipeline-parallel-size=2,这样每张卡压力小一点,但要注意pipeline的micro-batch设置,尽量让各stage的显存负载均衡。另外量化是必须的,int8至少能砍掉一半显存占用,4bit的话用GPTQ或者AWQ,实测70B模型在4bit下8卡跑起来舒服很多,速度也还过得去。
至于只用4张卡,我反而觉得不推荐,因为70B模型4卡即便是int4也要接近单卡40GB,3090肯定爆,除非你用offload到CPU,但那样延迟会很高。真要是嫌麻烦,直接上70B的量化版配TP=8,但把KV cache的调度策略调一下,比如设置--kv-cache-dtype fp8,或者限制max-num-seqs,能救回来不少显存。
还有个细节,你启动时OOM可能跟vLLM默认的预分配内存有关,试试--gpu-memory-utilization设到0.9,留点余量给CUDA context,别一上来就顶着上限跑。最后建议先跑个benchmark脚本看每张卡的实际显存峰值,再动态调TP和PP的组合,别盲抄网上的参数。
8卡全上反而容易卡在通信瓶颈,试试tensor-parallel=4加流水线并行,再上int8量化稳得多。
8卡3090跑70B其实算力是够的,但显存瓶颈不在总容量,而在KV cache和activation的峰值占用。你直接tp=8踩了个大坑,3090的PCIe带宽在卡间通信时会成为瓶颈,而且70B的模型并行维度太大,每层计算量反而被通信延迟拖垮了,推理慢是必然的。我建议你试试tp=4加pp=2,把张量并行控制在四卡以内,流水线并行切成两层,这样每张卡的显存占用能压到17-18GB左右,给KV cache留出余量。另外量化真的得做,int8在vLLM里支持得不错,显存直接砍半,4bit的话用GPTQ或者AWQ,但注意有些算子会降精度影响输出质量。如果只上4张卡,tp=4跑int8是稳的,但速度肯定不如8卡,毕竟算力减半。还有个骚操作是开offload,把不常用的层临时挪到内存,但3090的主机内存带宽够呛,速度会掉一个量级。你试下tp=4 pp=2加int8,显存占用大概在14GB左右,应该能跑起来,速度比tp=8快不少。最后问下你用的什么框架版本,vLLM老版本对pp支持有bug,升级到0.4以上再试。
试试tp=8加--kv-cache-dtype fp8,能省不少显存,速度慢可能是没开continuous batching。
TP=8加GPTQ量化到4bit稳得很,8张卡跑满也就15GB左右,速度还快不少。
说实话你这个问题我上个月刚踩完坑,8卡3090跑70B理论上显存够,但实际卡在KV cache和中间激活值上。tensor-parallel-size=8确实会让每张卡的通信开销爆炸,尤其3090的PCIe带宽扛不住,速度慢很正常。我建议试试tensor-parallel-size=4加pipeline-parallel-size=2,这样每张卡显存占用能压到18GB左右,同时通信压力小很多。量化方面int8是必须的,AWQ或者GPTQ都行,4bit也能跑但质量下降明显,尤其长文本生成时。如果你只求稳定,4卡跑TP=4确实更舒服,显存余量足,速度反而比8卡TP=8快,因为省去了跨卡同步的等待。另外别忘了给vLLM加--gpu-memory-utilization 0.9,默认0.8太保守,还有--max-model-len别设太高,4096就够了,不然KV cache会吃掉大量显存。我最后是用的TP=4+PP=2+int8,跑Llama 2 70B生成速度大概15 tokens/s,显存稳定在20GB每卡,你可以参考下这个配置再微调。
试试TP=4+PP=2,配合AWQ量化,跑起来稳得多,单卡占用能压到17G左右。
这题我刚好踩过坑,8卡3090跑70B纯tensor parallel就是会卡在通信瓶颈上,显存看着够但KV cache和中间激活值一算就爆。建议试试tp=4加pp=2,把张量并行降下来减少跨卡通信,同时用vLLM的--max-num-seqs调小点,比如64,能省不少显存。量化的话int8比较稳,awq或gptq都行,基本不掉点,但4bit能上就别犹豫,速度提升很明显。4卡跑反而稳这个说法对了一半,主要是通信开销小了,但吞吐量会降,如果只是自己玩可以接受。
8卡3090跑70B其实卡在KV cache上,你TP=8的时候每张卡光权重就占13GB左右,剩下11GB给激活和缓存确实紧。建议试试TP=4+PP=2,把序列长度和batch调小点,比如max-seq-len 2048、batch 4,能稳不少。量化的话int8够用,AWQ或GPTQ都行,显存能省一半,但速度提升有限。4卡跑其实更省心,TP=4配量化,吞吐比8卡硬扛还高,你可以先拿4卡验证下。
楼上说的TP=4+PP=2是个思路,但我实测下来PP在vLLM里对单请求延迟不太友好,调度开销大。你不如直接TP=8但开--enable-chunked-prefill,再把--max-num-batched-tokens压到4096,OOM基本能解决。另外别忽视CPU offload,把KV cache的20%放内存,慢是慢点但至少不爆。量化我推荐fp8,3090不支持但vLLM有模拟fp8,省显存效果比int8好。
我猜你可能没开--gpu-memory-utilization,默认只用到90%显存,8卡实际可用就172GB,再扣掉CUDA context和碎片,OOM很正常。直接
看到你说tp=8反而慢,我第一反应是通信瓶颈,8卡之间NVLink带宽扛不住全量张量并行的同步开销,尤其3090这卡P2P走的还是PCIe,性能打折很厉害。我建议你试试tp=4加pp=2,把显存压力分散到两个流水线阶段,每张卡大概能压在18GB左右,推理延迟反而比硬上tp=8好看。不过pp的切分得注意层数别太碎,70B一共80层,按40/40分比较合理,micro-batch设个16或者32,吞吐能拉起来。量化的话,int8基本无感,AWQ或GPTQ的4bit能直接砍到11GB每卡,但如果你追求输出质量,还是别降精度,毕竟3090跑bf16原生算力最稳。另外你提的只用4卡方案我试过,显存肯定够,但batch size稍微大点就吃紧,而且算力利用率不如8卡并行高,除非你完全不在乎吞吐只求单次推理快。最后提醒个坑,vLLM的KV cache也占显存,记得把gpu-memory-utilization调到0.9,再给swap空间留点余量,不然就算切分对了也会莫名OOM。