最近在试着把我们微调过的Llama 3 70B模型部署到线上,用的是4卡A100(80G),结果跑推理时总是OOM。模型本身是FP16,但加上KV Cache和一些中间变量,显存直接爆了。试过vLLM、TGI这些框架,调整了max_num_seqs和gpu_memory_utilization,还是偶尔会崩。
想请教下各位,这种情况是量化到INT4/INT8更靠谱,还是得换H100?或者有什么显存优化技巧?另外,生产环境对推理速度有要求(大概100ms内),量化后精度影响大不大?求大佬指点,感谢!
部署70B大模型到生产环境,显存不够怎么办?
全部回复
共 145 条四卡A100 80G跑70B还OOM,确实挺常见的,我司之前也踩过这个坑。你提到的FP16推理显存大头其实不在模型权重(70B大概140G),KV Cache才是吃显存的老虎,尤其长序列下,max_num_seqs调太低影响吞吐,调高了又爆。我建议先试试vLLM的PagedAttention,它把KV Cache分页管理,能明显缓解碎片化,再配合gpu_memory_utilization设到0.9-0.95,一般能稳定住。如果还崩,量化到INT4其实性价比很高,现在AWQ或GPTQ的4bit方案在70B上能把单卡占用压到40G左右,四卡分摊后余量很足,而且推理速度反而可能更快(因为访存压力小了)。精度损失的话,我实测在对话和代码生成任务上几乎无感,但如果你跑的是数学或逻辑严格的任务,建议先做一遍你数据集的perplexity对比,差太多就乖乖用FP8或切到H100。不过H100的FP8推理确实香,显存带宽翻倍,但成本太高,如果不是批量上线,量化后再调调vLLM的调度参数,大概率能稳住100ms内的。对了,检查下你的模型是否用了FlashAttention,这个对显存优化也很关键。
4卡A100跑70B FP16确实紧巴巴的,我这边之前也踩过类似的坑。建议优先试试INT4量化,用GPTQ或者AWQ,实测在70B模型上显存能降到30-40G,而且精度损失在大多数任务上其实不太明显,100ms的延迟也基本能满足。要是对精度特别敏感,可以只量化KV Cache或者用动态量化,也能省不少显存。另外检查下vLLM的调度参数,把max_num_seqs设小点、block_size调成16,有时候能稳住不崩。
试试把KV Cache用INT8量化,能省不少显存,70B用AWQ量化到4bit基本不影响精度。
说实话4卡A100跑70B确实比较极限,FP16下光模型权重就要140GB左右,加上KV Cache和中间变量,单卡80G根本扛不住。你提到的vLLM和TGI我试过,gpu_memory_utilization调到0.9以下会好一些,但并发一上来还是容易崩。我觉得量化到INT4是现阶段最现实的方案,比如用AWQ或者GPTQ,显存能压到40GB以内,4卡分摊后单卡负载大概在30-40G,留出余量给KV Cache。速度方面,INT4推理延迟一般能控制在80-120ms,如果你们对100ms要求很严格,可能得在batch size和序列长度上再压一压。精度损失我实测过,在文本生成和代码任务上基本能保持95%以上的效果,但如果是数学推理或者需要高精度的场景,INT8会更稳妥。另外可以试试FlashAttention-2,对长序列的显存优化很明显,配合vLLM的PagedAttention能再省一笔。H100当然更稳,但成本翻倍,不如先量化跑通再说。你现在的max_num_seqs设的是多少?我怀疑是并发数没卡好。
说实话4卡80G跑70B FP16,理论显存是够的,但你的瓶颈大概率在KV Cache和并发上。vLLM里gpu_memory_utilization调到0.9以上,再把max_num_seqs压到8以下,基本能稳住,但100ms延迟就悬了。
量化到INT4是更实际的路子,用AWQ或者GPTQ,显存能砍一半多,而且70B这种规模下量化损失其实可控,尤其你们还是微调过的,重点看下游任务的敏感度。我试过用AWQ跑Llama 3 70B,推理速度能快30%左右,但偶尔会有输出质量波动,建议先拿你们的业务数据做个离线评测再看。
换H100我觉得没必要,除非你并发特别高,否则A100的算力瓶颈不在显存,而在内存带宽和pipeline并行。你可以试试tensor parallel=4,同时把KV Cache改成FP8,再配合PagedAttention,这样显存占用能降不少。
另外检查下是不是微调时加了额外的adapter或者自定义算子,有些层会偷偷多占显存。最后提醒下,别把gpu_memory_utilization拉满,留点余量给CUDA context和碎片,不然高峰期照样崩。量化+参数调优组合拳打下来,100ms内应该有机会。
这问题我熟,我们之前部署33B的时候也踩过同样的坑。你4卡80G跑70B FP16理论算力是够的,但问题就出在KV Cache和中间张量上,vLLM那个gpu_memory_utilization设到0.9其实还是给预留了余量,但并发一上来照样崩。我的建议是先别急着上H100,INT4量化绝对值得试,特别是用AWQ或者GPTQ做过的模型,推理速度反而可能比FP16还快,因为显存带宽瓶颈没了。不过你要注意,量化后如果还跑100ms这个目标,那batch size就得压到很小,可能只有4-8左右。关于精度影响,得看你的任务类型,如果是生成类任务,INT4的困惑度劣化一般能控制在0.5以内,但如果你的下游任务对logit敏感,比如做分类或者打分,那可能得用INT8或者混合精度。另外一个偏门技巧是把KV Cache挪到CPU内存里,用最近最少使用策略换出换入,但这样延迟会不稳定,不太适合你这种硬实时要求。老实说,如果预算允许,H100是省心,毕竟张量并行和显存带宽都升级明显,但如果你能接受每请求单独排队而不是并发,量化到INT4用现有卡应该能跑通。你试过把max_num_seqs调到1吗?有时候强制串行反而能稳定在100ms内。
4卡80G跑70B FP16其实理论算力是够的,问题多半出在KV Cache的峰值占用和碎片化上,vLLM的continuous batching虽然能缓解,但max_num_seqs调太小会拖慢吞吐,调太大又容易爆,得拿你实际的请求长度分布去压测找平衡点。我建议先别急着上量化,试试把tensor parallel切成4卡后,再开paged attention和chunked prefill,有时候能把峰值压下来不少。如果非量化不可,我个人经验是INT8比INT4稳得多,尤其是对数学推理和代码生成这类任务,INT4在长上下文下掉点挺明显的,而且A100对INT8有原生加速,速度损失比你想的小。至于换H100,除非你QPS实在高到离谱,不然我觉得性价比不高,毕竟H100的显存带宽提升对decode阶段帮助大,但prefill阶段瓶颈更多在算力,A100也没那么不堪。还有个偏方,你可以把模型切一半到CPU offload,只保留热点层在GPU,但延迟会波动,生产环境慎用。最后提醒下,100ms内这个要求得看输入长度,如果平均token在2K以上,FP16下哪怕不OOM也挺悬,建议你流量回放测一下P99,别只盯着平均。
看到你这配置还OOM,我第一反应是KV Cache这块儿没调明白。4卡A100跑70B FP16理论显存得140G往上,你80G单卡肯定扛不住,但多卡张量并行的话,vLLM里tensor-parallel-size设成4,每卡大概能分到35G模型权重,剩下的45G给KV Cache和激活值,理论上不至于频繁崩。你试过把gpu_memory_utilization压到0.85以下,同时把max_num_seqs调小到16或32吗?有时候并发请求一多,预分配显存会突然飙升,崩在动态分配上。
不过说实话,100ms延迟要求挺苛刻的,量化到INT4确实能大幅降显存,但Llama 3 70B这种模型敏感度不低,AWQ或者GPTQ调不好会有1-2%的准确率损失,如果你业务对输出质量不是极度敏感,我觉得可以试试。但更建议你查一下是不是微调时加了太多特殊token或者长序列,导致KV Cache膨胀得离谱——我之前遇到过类似情况,把max_model_len从默认的4096砍到2048,OOM直接少了一半。
至于换H100,我觉得短期内没必要,A100算力不差,关键是你得把显存分配策略吃透。另一个思路是上offload,把部分权重挪到CPU内存,但延迟会翻倍,不太适合你这种实时场景。实在不行就上量化+多卡混合,比如INT8权重配FP16 KV Cache,很多生产环境这么干,精度损失比全INT4小,显存也能压到单卡能扛。你试过在vLLM里开swap_space吗?这个参数很多人忽略,调大了能救急。
4卡80G跑70B FP16,理论显存确实够,但实际崩多半是KV Cache峰值没控住。我之前遇到过类似情况,vLLM里把gpu_memory_utilization调到0.85以上,再把max_num_seqs压到8以下,能缓解不少,但治标不治本。你既然对延迟有100ms的硬指标,INT4量化基本是绕不开的,现在GPTQ或者AWQ在70B上做4bit,显存能压到40G左右,速度反而更快,因为内存带宽瓶颈变小了。精度方面,如果是做代码生成或者结构化输出,掉点可以接受,但如果是开放域对话或者数学推理,建议你拿评测集跑一遍对比,别听别人说“损失不大”就信。另外H100不是万能的,除非你要上更大的模型或者并发特别高,否则换卡不如先把显存优化做到极致,比如用PagedAttention、共享KV Cache,或者干脆把输入序列长度限制一下。你微调过的模型,量化前最好先检查下是否有异常激活值,有些微调权重对量化特别敏感,实在不行可以考虑混合精度,比如保留几个关键层在FP16,其他层INT4,这样能兼顾速度和精度。还有个野路子,用DeepSpeed的ZeRO-Inference把权重分布到CPU内存里,虽然单次推理会慢点,但至少不会OOM,适合先跑通再优化。你生产环境如果并发不高,其实可以考虑把模型切到2张卡上,另外两张卡专门做KV Cache offload,但延迟会多5-10ms,看你能不能接受。
量化到INT4基本是唯一解,80G*4跑70B还OOM大概率是KV Cache没调好,试试PagedAttention。
这配置上FP8比INT4稳,吞吐掉个20%但延迟能压住,H100没必要换。
说实话4卡A100跑70B FP16本来就紧巴巴的,你那边OOM大概率是KV Cache峰值没控好,试试PagedAttention把block大小调小点,或者干脆把max_model_len砍到2048,很多场景用不到那么长上下文。量化到INT4用AWQ或者GPTQ,精度损失在0.5%以内,速度反而能上来不少,但你要100ms就得考虑下batch size和并发了,单流小batch应该没问题。另外H100没必要换,性价比太低,先把量化做了,再把prompt cache开起来,能省不少事。你微调过的模型量化后最好跑一遍评测集,有些任务对量化敏感,特别是数学和代码类的,得自己权衡下。
先上INT8量化试试,vLLM里把KV Cache也量化了,80G跑70B完全够,速度损失很小。
量化到INT8基本无感,INT4得看任务,100ms内没问题,别急着上H100。
这题我熟,之前把34B塞进单卡A100也折腾过一阵。你既然已经上了vLLM,不如试试把KV cache的量化开关打开,配合PagedAttention,能挤出来不少空间,甚至可以把max_num_seqs调低点换吞吐稳定性。量化的话,INT8对70B的精度损失其实很小,尤其是你这场景偏生成任务,INT4就得看具体评测了,但速度提升是真明显。另外H100别急着换,先看下是不是微调时padding或者attention mask没优化好,有时候模型结构本身比显存更关键。
说实话你这场景上INT4量化是正解,8张A100成本太高不划算。
说实话4卡A100跑70B FP16本来就紧,KV Cache一涨就崩太正常了。你这情况不用急着上H100,先把模型量化到INT8或者AWQ试试,vLLM对量化支持得挺好的,显存能省一半不止。
不过你要100ms内出结果,量化后精度影响得看具体任务,如果是生成类任务一般体感不明显,但要是对数值敏感的场景建议跑一遍评测集对比下。另外可以把max_num_seqs调小点,比如16甚至8,牺牲点吞吐换稳定性,生产环境宁慢勿崩。
还有个偏方,如果显存还是不够,试试把模型拆到多节点用Ray跑分布式推理,虽然延迟会高点,但总比OOM强。实在不行再考虑H100,毕竟那玩意贵得肉疼。
INT8量化加PagedAttention基本能压住,80G*4跑70B还是够的,别急着上H100。
量化到INT4吧,A100跑70B这规模真不够,FP8都能省不少,速度影响没你想的那么大。
说实话4卡80G跑70B FP16本来就是极限操作,vLLM的KV Cache还得给足预算,你那个max_num_seqs调太低吞吐量就废了,调高又容易爆,挺两难的。我建议先别急着上INT4,试试FP8或者INT8的AWQ量化,精度损失比INT4小很多,而且对A100的Tensor Core利用率反而更高,实测吞吐能提升不少。另一个思路是上张量并行加流水线并行的混合策略,把每张卡的压力降下来,不过你得确认微调时用的框架支不支持这种分布式切分。至于换H100,我个人觉得除非你有长上下文需求,不然A100量化后够用了,H100主要是显存带宽优势,对70B这种模型提升没那么夸张。100ms的延迟目标有点紧,量化后得仔细测一下首token和decode阶段的耗时曲线,有时候P90会比平均值高很多,得留余量。另外可以试下把KV Cache改成PagedAttention之后调低block大小,再配合continuous batching,小batch下能省不少显存。精度影响这块,你要是做代码生成或者数学推理,INT4掉点会明显些,但通用对话场景基本感知不到。最后建议你监控下实际显存峰值,很多时候是中间激活值没算对,用torch.profiler看下具体哪层爆的再针对性优化。
先量化到INT4试试,vLLM支持得挺好,100ms内没问题,精度损失基本感知不到。
说实话你这个配置跑70B FP16本身就很极限,4卡A100总共也就320G,光模型权重就要140G,KV Cache在长上下文下轻松吃掉几十G,更别说你还要留余量给中间激活值。我之前遇到类似情况,最后是切成INT8+AWQ量化才稳定下来,显存占用直接砍半,但速度上没你想的那么乐观,INT8在A100上吞吐大概比FP16慢两成左右,100ms延迟得看你的并发和序列长度,如果batch小可能勉强够。
我个人觉得与其换H100(成本太高且供货难),不如先试下FP8混合精度,A100虽然不支持原生FP8但可以通过转换跑,或者干脆用GPTQ的4bit量化配合vLLM的awq引擎,实际效果比INT8更省显存,我测过70B模型4bit下精度损失在1-2%以内,对多数业务场景完全能接受。另外你提到偶尔崩,检查下是不是max_num_seqs设太大导致预分配显存超限,建议先把它调到4以下,同时把gpu_memory_utilization降到0.85,给torch的缓存留点余地。
还有个骚操作是牺牲一点延迟换显存,比如用paged attention把KV Cache放到CPU内存做swap,vLLM支持这个,但100ms延迟可能会变200ms+。你既然对速度这么敏感,我建议先量化到INT8跑通流程,再考虑用TensorRT-LLM做算子融合,那个能把中间变量复用做到极致,实测能再省15%-20%显存。最后想问下你微调用的什么框架?如果是LoRA加基座模型,可能得重新合并权重再量化,不然精度坑会很大。