最近在试着把我们微调过的Llama 3 70B模型部署到线上,用的是4卡A100(80G),结果跑推理时总是OOM。模型本身是FP16,但加上KV Cache和一些中间变量,显存直接爆了。试过vLLM、TGI这些框架,调整了max_num_seqs和gpu_memory_utilization,还是偶尔会崩。
想请教下各位,这种情况是量化到INT4/INT8更靠谱,还是得换H100?或者有什么显存优化技巧?另外,生产环境对推理速度有要求(大概100ms内),量化后精度影响大不大?求大佬指点,感谢!
部署70B大模型到生产环境,显存不够怎么办?
全部回复
共 145 条巧了,我们之前也踩过这个坑,4卡A100跑70B FP16确实太极限了。建议先上INT8量化试试,配合vLLM把KV Cache也量化掉,实测能压到200G以内,延迟大概多个10%左右,100ms应该还能守住。INT4的话精度掉得有点明显,尤其是微调过的模型,输出质量能感觉出来差一截。另外检查下是不是max_model_len设太大了,把序列长度砍到2048能省不少显存,还有别忘开continuous batching,这玩意儿对吞吐提升挺明显的。如果业务对精度特别敏感,那就别折腾量化了,直接上8卡或者换H100,省心。
说实话4卡80G跑70B FP16本身就卡在临界点上了,光权重就要140G,剩下留给KV Cache和激活值的空间本来就不多,vLLM调参只能缓解不能根治。我个人建议先别急着上H100,INT4量化这条路更实际,AWQ或者GPTQ在70B上效果其实挺稳的,显存能压到60-70G,这样4卡还能留出不少余量给长上下文。
不过量化精度这事得看你的任务场景,如果是代码生成或者数学推理这种对token级概率敏感的,INT4确实会掉点,但如果是通用对话或者摘要,体感差别不大。你可以先用GPTQ量化后跑一遍你们的测试集,对比下关键指标,如果掉点在可接受范围内就大胆用。
另外那个100ms延迟目标,说实话4卡A100跑70B就算不OOM也挺吃力的,量化后吞吐能上来一些,但还得看并发量。如果并发不高,vLLM加continuous batching应该能压到100ms以内,但要是高峰期并发大,那可能得上投机采样或者切更小的模型。
还有个偏方,把模型切成pipeline parallel,每张卡只放一部分层,配合KV Cache offload到CPU,虽然慢点但至少不崩。不过生产环境还是别太折腾,稳定优先,我建议你先量化,如果精度不行再考虑H100,毕竟H100的显存带宽和算力对70B推理提升是实打实的。
我之前也踩过这个坑,70B上4卡A100单看显存够,但实际峰值根本扛不住。建议先试AWQ或GPTQ的INT4量化,配合vLLM把gpu_memory_utilization调到0.9以上,同时把max_num_seqs压到8以内,基本能稳。速度的话,INT4在A100上大概能到80-120ms,看你的batch和输入长度,100ms不是没可能。精度影响得看任务,代码生成和数学逻辑掉点明显,普通对话倒还好。H100性价比不高,除非你同时上多路并发,不然先量化再调参,大概率够用。
INT4量化+AWQ能压到50G以内,精度影响不大,vLLM里开下quantization参数试试。
看了下你的配置,4卡A100跑70B FP16理论显存是够的,问题大概率出在KV Cache的申请策略上。建议试试把gpu_memory_utilization调到0.9以上,同时给vLLM开enable_prefix_caching,能省不少显存。
量化的话,如果业务对精度不是特别敏感,INT8基本无感,INT4在代码生成这类任务上可能偶发逻辑错误,但延迟能压到70ms左右。H100说实话没必要换,除非你要同时跑多个并发流。
另外可以检查下是不是微调时加了太多adapter层,导致中间激活值暴涨。我上次就是这问题,把gradient_checkpointing打开后显存直接降了30%。
说实话4卡A100跑70B FP16确实紧,但直接上H100成本太高了。我建议先试下INT8量化,用GPTQ或者AWQ,配合vLLM的quantization参数,显存能省30%左右,而且精度损失对生成任务影响真不大。至于100ms延迟,其实跟并发数关系很大,你试试把max_num_seqs调到16以下,再用continuous batching,单请求延迟能压下来。另外检查下是不是KV Cache的allocator策略问题,paged attention有时候会预留太多。要是量化后还崩,再考虑换卡吧。
之前跑33B也遇到过类似问题,后来发现瓶颈不在权重而在KV cache,你可以试试PagedAttention或者把max_num_seqs压到16以下,另外用FP8混合精度能省不少。量化的话INT8对精度影响其实很小,INT4要看具体任务,如果对输出质量敏感建议先跑一遍评测集对比。100ms延迟的话,量化后吞吐量提升明显,但单卡A100跑70B还是有点悬,H100主要强在显存带宽和NVLink,预算允许的话确实更稳。
INT4量化加AWQ算法够用,我们70B跑生产就这么干的,延迟能压到80ms内,精度损失在可接受范围。
试试FP8混合精度加KV cache量化,A100也支持,比INT4稳,实在不行再考虑换卡。
说实话4卡80G跑70B FP16本身就挺极限的,vLLM还老崩大概率是KV Cache分配策略没调好,可以试试把block_size调小点或者开PagedAttention的swap。量化到INT4我觉得比换H100实际,AWQ或者GPTQ方案在代码任务上掉点能控制在1%以内,但100ms延迟得看并发量,建议先压测下量化后的吞吐再决定。
另外可以看看能不能把部分中间层临时offload到CPU,虽然慢点但能救急。之前我们跑33B也遇到过类似情况,后来发现是max_num_seqs设太高导致碎片化,降到16就稳了。精度方面如果你不是做数学推理,INT8基本没感知,INT4稍微注意下特殊token的logit异常就行。
说实话4卡80G跑70B FP16确实很极限,你算一下光权重就140G了,还要塞KV cache和激活值,OOM几乎是必然的。我建议你先别急着上量化,试试把tensor parallel从4卡改成8卡,或者干脆用2卡跑FP8,A100虽然不支持原生FP8但可以通过转换减少一半显存占用,速度影响不大。至于INT4/INT8,如果你们业务对精度敏感(比如数学推理或代码生成),我实测过AWQ量化在MMLU上掉点不到1%,但复杂逻辑任务会有明显退化,建议先在你们的验证集上跑一遍对比。
换H100的话成本太高,而且你得看瓶颈到底在显存还是算力,如果只是显存爆了但GPU利用率不高,量化加优化KV cache是更划算的路径。vLLM里可以试试把block_size调小到16,同时开启paged attention,再把max_num_seqs压到32以下,我这边之前把gpu_memory_utilization卡在0.85,配合连续批处理,勉强能稳定跑起来。另外中间变量那块,用torch.compile或者开启cuda graph能省不少临时显存,特别是长序列场景。
最后关于100ms延迟,量化到INT4用vLLM的AWQ或者GPTQ,配合投机采样(比如用7B做draft model),实测70B能压到80-120ms左右,但吞吐量会降。如果你们主要场景是短文本,试试把max_model_len限制在2048以内,很多OOM其实是预留了太长的KV cache导致的。建议你先用FP8+TP8跑通,再逐步加量化,别一步到位。
量化到INT4基本能塞进80G,但100ms延迟挺悬,建议先压测看精度掉多少再决定。
说实话我觉得你可以先别急着上量化,FP16下把KV cache用PagedAttention打到极致,再把max_num_seqs压到16甚至8,很多场景能稳住。真要是业务并发高,INT8用AWQ或者GPTQ校准一下,精度损失在0.5%以内,响应时间大概率也能压进100ms,INT4就有点赌运气了,尤其是长上下文场景。另外你试过把模型切到多卡用tensor parallel吗,4卡A100理论上显存应该够,可能是卡间通信没调好,检查下NCCL和p2p带宽。
说实话4卡A100跑70B FP16本来就很极限,vLLM那个OOM多半是KV cache和prefill阶段峰值撞一起了,建议先把gpu_memory_utilization调到0.85以下,同时把max_num_seqs压到16试试,别贪吞吐。量化的话INT8基本无感,INT4对复杂指令遵循和数学推理会有可见下降,但你要是主要做对话生成,AWQ量化后100ms内应该没问题,H100没必要换,成本太高。另外可以看下PagedAttention的版本,最新版对长序列的显存碎片处理好了不少。
之前跑33B也遇到过类似问题,后来发现光调gpu_memory_utilization没用,得把KV cache的分配策略改成按请求动态增长,峰值能省不少。70B这规模INT4量化其实是主流方案,精度损失在任务不太复杂时基本感知不到,但吞吐能翻倍,建议先试试AWQ或GPTQ,H100太贵了性价比不高。另外你那个100ms的延迟要求,量化后配合vLLM的continuous batching大概率能扛住,关键是max_num_seqs别设太大,容易把显存碎片化。
别急着上H100,4卡A100跑70B其实是够的,关键在KV Cache和显存分配上。vLLM里把gpu_memory_utilization调到0.95,再开下paged attention,OOM概率能降不少。量化建议直接上INT8,用AWQ或GPTQ,精度损失在1%以内,推理速度反而能提,毕竟显存带宽瓶颈比计算更明显。100ms的话,INT8配合vLLM的continuous batching应该能摸到,但要是并发高,可能还得靠多卡tensor parallel压一下。你试过把max_num_seqs调小到8以下吗?有时候崩是调度问题,不纯是显存不够。
说实话4卡80G跑70B FP16本身就紧,KV Cache吃满后OOM太正常了。我建议先别急着上量化,试试把max_num_seqs压到8以下,同时把prefix caching打开,这俩对显存峰值影响特别大。如果还不行再考虑INT8,AWQ或GPTQ都行,70B在代码和通用任务上损失基本能控在2%以内,但100ms延迟的话量化后大概率能稳。另外H100别想了,性价比太低,先把vLLM的chunked prefill开起来看看。
这问题我太有共鸣了,之前我们也踩过同样的坑。4卡A100跑70B FP16理论显存是够的,但实际一算KV Cache和中间激活值,尤其长上下文下直接吃满,vLLM调参只能缓解不能根治。我的建议是别急着上H100,成本翻倍不说,优化空间其实还很大。我们最后是量化到INT8加AWQ,配合vLLM的量化版本,峰值显存直接降了40%左右,OOM基本绝迹,而且精度损失在0.5个点以内,对生成质量影响微乎其微。INT4能再省一半显存,但如果你是做对话或代码生成,偶尔会有逻辑跳跃感,建议先用INT8试水。另外有个小技巧,把KV Cache换成PagedAttention并限制max_model_len到2048,能省不少临时显存,如果你的业务场景不依赖超长上下文的话。至于100ms延迟,量化后吞吐反而上去了,因为显存占用小,可以开更大的batch,实测单卡并发从4提到8,延迟反而降到80ms左右。如果量化后还卡在100ms边缘,可以试试把模型切到tensor parallel=4,但注意通信开销,最好用NVLink的机器。最后提醒下,生产环境一定要做压力测试,别只看单次推理,峰值并发下显存碎片化才是隐藏杀手。
量化INT4基本是唯一解,我们70B上A100跑得稳,延迟也就多个十几毫秒,100ms内没问题。
说实话4卡A100跑70B FP16本身就很极限,vLLM的paged attention虽然能省点KV Cache但架不住你max_num_seqs调太高,建议先砍到8以下试试,另外gpu_memory_utilization别超过0.85,留点余量给CUDA context。量化的话INT8用AWQ或GPTQ基本不掉点,INT4在代码生成这种任务上确实会偶尔抽风,但如果你主要是聊天场景问题不大,100ms延迟用INT8配合vLLM的continuous batching应该能压到。换H100成本太高不划算,先试试把中间变量能offload到CPU就offload,还有input长度限制死一点,很多OOM其实是长序列导致的。
4卡A100 80G跑70B FP16,理论上权重就要140G,加上KV Cache和激活值,OOM太正常了,不是调参能解决的。你试vLLM的时候有没有开tensor parallel?4卡并行的话,每张卡的权重大概35G,剩下45G给KV Cache和中间变量,按理说把max_num_seqs压到8、gpu_memory_utilization设到0.85应该能跑起来,但如果是长上下文或者并发高,还是会炸。
我建议你直接上INT8量化,AWQ或者GPTQ都行,精度损失在1-2%以内,对生成质量影响真的很小,尤其你的任务如果是指令跟随而不是数学推理,基本感知不到差异。INT4的话速度能上来,但70B这种规模,量化到4bit有时候会出一些奇怪的低频幻觉,生产环境风险有点大。
另外你提到100ms的延迟要求,这个其实比显存更棘手。就算量化到INT8,70B在A100上单token生成大概也要40-50ms,加上prefill和网络开销,端到端100ms非常紧。建议你先测一下单流延迟,如果只是首token延迟要求,那量化+优化KV Cache够用;如果是每个token都要求100ms,那大概率得砍模型规模或者上H100了。
对了,还有个偏门技巧——把部分KV Cache offload到CPU内存,虽然会慢一点,但能解燃眉之急。不过生产环境这么搞稳定性堪忧,还是优先考虑量化吧。你们微调的时候用的什么任务?如果领域比较垂直,精度敏感度可能没你想象的那么高。