最近在尝试用DeepSpeed微调一个7B的LLaMA模型,卡是两张A100 40G。用了ZeRO-3,offload也开了,但每次跑起来没几分钟就报OOM。我看了一些教程说7B模型用ZeRO-3应该能跑,但我设置zero_optimization.stage=3之后,显存占用直接冲到35G以上,训练步数一多就崩。我试过调小per_device_train_batch_size到1,还是不行。是不是我offload_param和offload_optimizer的device没设对?或者ZeRO-3本身对多卡通信有额外显存开销?有没有大佬分享下实际成功跑7B微调的config配置?先谢过了。
用DeepSpeed跑LLaMA微调,ZeRO-3总报显存不足,是我配置有问题吗?
全部回复
共 112 条ZeRO-3确实有额外的通信和显存开销,尤其是多卡场景下,即使开了offload,activation和gradient的碎片化也容易炸显存。建议试试把per_device_train_batch_size降到1的同时,把gradient_accumulation_steps调大,另外检查下offload_param有没有设成cpu,offload_optimizer也建议用nvme或者cpu,别省这一步。我跑13B时踩过同样的坑,后来关掉ZeRO-3,只用ZeRO-2加offload反而稳住了,你可以对比下效果。
ZeRO-3确实会在多卡通信上吃掉不少显存,尤其是梯度分片后的all-gather操作。你可以试试把zero_optimization.stage3_gather_16bit_weights_on_model_save改成false,或者手动调小stage3_max_live_parameters和stage3_prefetch_bucket_size,这俩参数能显著降低峰值显存。另外offload_param设成cpu、offload_optimizer设成nvme试试,我这边7B用4张A100 40G这么配勉强能跑起来。
我最近也刚踩过这个坑,7B在两张A100上跑ZeRO-3确实挺极限的。建议你检查下offload_param和offload_optimizer是不是都设成了cpu,只offload optimizer的话显存压力还是很大。另外ZeRO-3本身会为每个参数维护分区状态,多卡通信的临时缓冲区也会额外吃显存,可以试试把communication_data_type改成fp16,或者加个gradient_accumulation_steps看看能不能缓解。
我之前也是两张A100 40G跑7B,跟你一样被ZeRO-3的显存问题卡了好久。后来发现offload设置里把offload_param和offload_optimizer都指向cpu,同时把pin_memory设成true,情况会好一些。另外多卡通信确实有额外开销,你可以试试把zero_force_ds_cpu_optimizer设为false,感觉能省点显存。还有一个小技巧是检查一下gradient_checkpointing是不是开着,这个对7B很关键。
试试把offload全扔CPU,batch size调到1,gradient checkpointing也打开,7B在40G上能跑。
哎这个坑我太熟了,之前用两张A100跑7B也卡了好久。其实ZeRO-3本身对通信的显存开销确实不小,尤其多卡之间同步参数时会有额外的buffer占用,35G往上冲挺正常的。你offload_param和offload_optimizer的device如果都设成cpu,按理说能省不少显存,但要注意offload_param设成cpu时,模型参数会在前向传播时频繁在CPU和GPU间搬动,速度会慢很多,而且如果CPU内存不够或者NVLink带宽不足,反而可能触发更多临时显存申请导致OOM。我试过把offload_optimizer放cpu,但offload_param保持gpu,再把per_device_train_batch_size压到1,梯度累积步数调大,这样能勉强跑起来。另外检查下你是否同时用了activation checkpointing,那个对7B模型很关键,能省大概一半激活显存。还有个小细节:ZeRO-3的reduce_bucket_size和allgather_bucket_size别用默认值,调小到5e7左右能减少通信峰值显存。如果还不行,试试ZeRO-2加offload,虽然参数不分区但显存开销反而更可控一点。
同两张A100跑7B,ZeRO-3确实容易踩坑,35G的起步占用我猜是offload没生效或者配置路径写错了。建议检查下offload_param和offload_optimizer的device是不是明确设成了cpu,还有pin_memory开不开影响也很大。另外多卡通信的buffer默认会吃不少显存,可以试试把zero_force_ds_cpu_optimizer设为false,或者手动调小communication_data_type为fp16,能省个几G。
我之前也踩过这个坑,ZeRO-3 offload参数和优化器到CPU后,通信量会暴涨,而且你两张卡之间NVLink带宽不够的话,反而会拖慢甚至卡死。建议你先别开offload,试试纯ZeRO-3加batch size=1,把梯度检查点打开,显存应该能压到25G左右。另外确认下你是不是把cpu_offload写成了device: cpu,我上次就是拼错导致没生效,白折腾半天。
ZeRO-3的显存开销确实不止参数本身,每层权重都要做all-gather,通信缓冲区会额外吃掉不少显存,两张40G其实挺紧的。你offload开了的话,建议把optimizer和param都指到cpu,同时试试zero_force_ds_cpu_offload这个选项,有时候能省点。另外检查下是不是stage3_gather_16bit_weights_on_model_save默认开着,那个也会临时拉高显存。我之前跑13B是四卡才稳,两卡7B不如直接试ZeRO-2加offload,速度可能还更快。
offload_param和offload_optimizer的device得设成cpu,而且要注意offload_param的pin_memory别开,不然反而占显存。我之前跑13B也遇到过,后来把zero_force_ds_cpu_optimizer设成false就好很多。另外ZeRO-3确实会有通信缓冲开销,你试试把zero_quantized_weights设成true,能省不少显存。还有个小坑,梯度检查得开,不然反向传播又得吃一波显存。
ZeRO-3的显存占用本来就是虚高的,35G起步很正常,关键是看稳态而不是峰值,你试试把zero_force_ds_cpu_offload设成true,然后offload_param和offload_optimizer的device都指到nvme,别用cpu。另外多卡通信确实会吃额外显存,你把communication_data_type改成fp16能省不少。我跑7B时是4张A100,batch size开到4才稳定,两张卡确实紧,建议再加pin_memory和num_workers调成0试试。
我之前也卡在这过,ZeRO-3的通信峰值比想象中高,尤其A100 40G跑7B其实很极限。你offload如果只开param没开optimizer,或者把optimizer留GPU上,照样会爆。建议直接把optimizer state全offload到CPU,然后zero_force_ds_cpu_optimizer设成false试试。另外你检查下是不是把gradient checkpointing漏了,那个能省不少激活显存。我最后是batch size=1加梯度累积,再加offload全开才稳住的,但速度确实感人。
我试过类似配置,7B在两张A100上跑ZeRO-3确实很紧,35G起步很正常,问题多半不是offload设错,而是通信buffer和梯度partition在stage3下会额外吃显存。你可以试试把zero_force_ds_cpu_optimizer关掉,再手动设zero3_use_mmap和zero3_use_all_gather,同时把eager_host_allocate打开,能省一点是一点。另外checkpoint保存频率别太高,save过程会临时拉高显存峰值,我上次就是死在保存上。
这问题我踩过,ZeRO-3的显存占用不只是模型参数,还有每层前向的all-gather临时buffer,7B在40G卡上其实很勉强。offload_param设成cpu之后,记得把pin_memory也开上,不然CPU和GPU之间拷贝会卡瓶颈。另外你试试把zero_force_ds_cpu_optimizer设成false,用adam offload到cpu,比默认的ds cpu adam省不少显存。还有个小坑,梯度检查得开,activation offload到cpu也能救一点,但会慢不少。如果还不行,干脆降到ZeRO-2加offload,7B真没必要硬上stage3。
ZeRO-3的显存峰值不只是模型参数,还有通信buffer和gradient checkpointing的临时张量,35G在双卡上其实挺正常的。你试试把zero_force_ds_cpu_optimizer设成false,然后offload_param的device写nvme试试,cpu offload有时候反而会因为pin memory吃满显存。另外确认下gradient_checkpointing开了没,这个对7B模型能省不少。我之前跑13B单卡40G都扛下来了,配置里把reduce_bucket_size和allgather_bucket_size调到5e8会舒服很多。
offload设成cpu试试,另外zero3通信量确实大,把zero_force_ds_cpu_optimizer关掉可能好点。
你这显存冲到35G大概率是通信缓冲区占的,试试调低zero3的allgather大小,或者换成stage2+offload更稳。
我之前也遇到过一模一样的情况,7B+ZeRO-3在A100 40G上确实能跑,但关键是把offload的device设成nvme,光靠cpu不行,因为通信缓冲区和临时张量也会吃显存。另外你检查下zero_force_opt和zero_allgather_bucket_size,把后者调小到5e7能明显降低峰值。还有个坑是train_batch_size全局batch和梯度累积别设太大,否则多卡同步时每个step的临时显存会叠加。建议先不开offload,纯ZeRO-3把batch调1试跑几百步,看峰值稳定在多少,再逐步加offload。
offload设成cpu试试,另外把zero3的通讯池调小点,A100 40G跑7B本来就紧巴巴的。
我之前也踩过这个坑,7B在40G卡上其实挺尴尬的,ZeRO-3本身分区参数和梯度会引入额外的通信缓冲,这部分显存开销很容易被忽略,尤其两张卡通信时all-gather的临时buffer可能直接吃掉几个G。你offload开了的话,检查下offload_param是不是用了nvme而不是cpu,如果device设成cpu但路径没配好,反而会把显存搞炸。另外有个比较隐蔽的点,zero_optimization里reduce_bucket_size和allgather_bucket_size默认值对7B来说偏大,我调到5e7甚至2e7之后显存峰值能降不少。还有就是你per_device_train_batch_size=1但gradient_accumulation_steps如果没跟着调,优化器状态更新频率太高,ZeRO-3在每步all-gather时都会把整个模型参数拉回来,所以显存曲线会随着步数上涨,可以试试开zero_allow_untested_optimizer再加stage3_gather_16bit_weights_on_model_save,但训练时最好把stage3_prefetch_bucket_size调小。说实话两张A100跑7B全参数微调真的紧,我后来直接切到LoRA加ZeRO-2才稳,要不你也先试试把stage降回2,或者用quantization。
说实话你这个问题我太有共鸣了,之前我也在两张A100上折腾过7B,ZeRO-3开offload之后显存看着是降了,但训练一跑起来就飙,后来发现是通信缓冲区和碎片化的问题。你试下把zero_optimization里的allgather_bucket_size和reduce_bucket_size调小一点,比如都设成5e7,这俩默认值经常是显存刺客。另外offload_param和offload_optimizer的device设成nvme其实不太推荐,除非你有特别快的SSD,不然还是留在cpu上更稳,但这样CPU内存得够大,32G可能有点悬。你batch size已经调到1了还崩,那大概率不是激活值的问题,反而是ZeRO-3在做参数分区时每个layer的meta信息也会占显存,你可以开一下zero_force_ds_cpu_optimizer试试,有时候能省不少。还有个小坑,如果你用了gradient_checkpointing,记得和offload配合时要把offload_optimizer的pin_memory设成false,不然反而增加显存压力。我最后是换了ZeRO-2加offload optimizer才稳定跑完的,虽然慢点但至少不崩,你可以先拿这个兜底。