最近在试着用LoRA微调7B的LLaMA模型,机器是两张3090(24G),按说应该能跑吧?但一加载模型就报CUDA out of memory。
我参考了几个GitHub仓库,有的说用bitsandbytes量化成4bit就行,但我试了还是炸。是不是我dataloader的batch size设太大了(设了4)?还是说需要把模型分到多卡?
另外,我看很多人直接用Hugging Face的Trainer,是不是里面有些默认参数会爆显存?有没有什么通用的显存优化trick,比如gradient checkpointing到底该咋开?
求各位大佬指点,真的有点怀疑人生了……
用PyTorch微调LLaMA,总是OOM,是我显存不够还是代码有问题?
全部回复
共 170 条7B模型用两张3090跑LoRA按理说够的,我猜问题可能出在加载基座模型时没开4bit量化,或者bitsandbytes配置没写对导致还是按16bit加载。batch size设4对于7B模型确实偏大,可以先调到1或者2试试,另外gradient checkpointing在Trainer里直接传gradient_checkpointing=True就能开,能省不少显存。还有注意一下Hugging Face的Trainer默认会加载模型到第一张卡上,需要手动用device_map="auto"做多卡分载。
7B模型用LoRA单卡24G应该勉强能跑,但batch size设4确实偏大了,尤其如果序列长度也长的话。建议先调成1试试,同时把gradient checkpointing打开,在Trainer里设置gradient_checkpointing_enabled=True就行。另外bitsandbytes的4bit量化需要加载时加load_in_4bit=True,如果你用的是旧版transformers可能不兼容,升级到最新版再看看。多卡的话可以用device_map="auto"自动分配,两张3090应该能分摊不少压力。
说实话7B模型用两张3090跑LoRA按理说够的,batch size=4确实偏大了,降到1或2试试,同时记得把gradient_accumulation_steps调高。gradient checkpointing在Trainer里直接设gradient_checkpointing_enabled=True就行,能省不少显存。另外检查下是不是没把模型加载到正确的设备,或者bitsandbytes的4bit配置里double_quant没开。
24G双卡跑7B LoRA理论上是够的,batch size设4对7B来说确实偏大了,先降到1试试,不行的话看看是不是加载了全精度模型。gradient checkpointing可以在Trainer里加--gradient_checkpointing参数直接开,能省不少显存。另外4bit量化最好用bnb_4bit_compute_dtype=torch.float16,不然默认float32还是容易炸。
老实说两张3090跑7B的LoRA按理说真不该炸,我怀疑问题出在模型加载时没有用device_map="auto"或者显存碎片没清理干净。你试过在加载模型前先torch.cuda.empty_cache()吗?有时候dataloader的batch size设4确实偏大,尤其如果序列长度超过1024的话,建议先调到1试试能不能跑通。gradient checkpointing在Trainer里直接设args.gradient_checkpointing=True就行,能省不少显存但会拖慢训练速度。bitsandbytes的4bit量化其实挺吃配置的,我遇到过某些版本的bnb和transformers不兼容导致显存不降反升的情况,你可以试试把load_in_4bit换成load_in_8bit或者手动指定bnb_4bit_compute_dtype。另外Hugging Face的Trainer默认会启用分批前向传播,但如果你没设置remove_unused_columns=False,它可能会额外缓存一些中间变量。实在不行就试试用deepspeed stage2或者ZeRO-3 offload,把优化器状态扔到CPU上,两张卡应该能撑住。
单卡24G跑7B加LoRA确实会爆,batch size改1开梯度检查点,再加个4bit量化基本能稳。
两张3090跑7B的LoRA按理说完全够,问题大概率出在加载方式上——试试用device_map="auto"配合bitsandbytes的4bit量化,同时把load_in_4bit=True和bnb_4bit_compute_dtype=torch.float16加上,能省不少显存。Batch size设4对7B来说其实还行,但dataloader的num_workers别设太高,不然CPU预加载也会抢显存。Gradient checkpointing直接在Trainer里设gradient_checkpointing_enabled=True就行,实测能省30%左右显存,另外注意Hugging Face的Trainer默认会缓存中间激活值,关了能再挤出点空间。
老实说,7B模型在双3090上跑LoRA按理说真不应该炸,batch size=4虽然不小,但也不是特别离谱,问题很可能是出在模型加载方式上。你可能用了默认的fp32加载,那光模型权重就吃掉28G左右,两张卡单张24G根本放不下,即使张量并行也要考虑通信开销。你说的bitsandbytes量化成4bit,得确认一下是不是真的在加载时传了load_in_4bit=True,而且还要配合torch_dtype=torch.float16,不然可能还是按bf16或者fp32在跑。另外gradient checkpointing确实很有用,在Trainer里设置--gradient_checkpointing 1或者model.gradient_checkpointing_enable()就行,它会用计算换显存,大概能省30%到50%的占用。还有一个容易被忽略的点:Hugging Face的Trainer默认会缓存所有中间激活值,如果你用了多卡,可能每张卡都在重复缓存,建议用DataParallel或者model parallel手动分配层数。不妨先试试单卡跑batch size=1,加上4bit量化和gradient checkpointing,看能不能跑通,再逐步调大batch size。如果还炸,检查一下dataloader有没有设置pin_memory=True,这个有时候也会偷偷多占显存。
3090 24G单卡跑7B全量微调确实容易爆,但你用LoRA还炸大概率是代码层面没优化到位。batch size设4不算大,关键看你是不是忘了开gradient checkpointing,在Trainer里设gradient_checkpointing_enabled=True就能省不少显存。另外bitsandbytes4bit量化后如果还OOM,检查下是不是加载时没设device_map="auto",或者试试把模型用accelerate的init_empty_weights先占位再加载。反正我经验是两张卡最好手动分下模型,光靠Trainer自动分配有时候会不均匀。
7B模型用4bit量化加LoRA,两张3090跑batch size 4按理说不会炸,但Hugging Face的Trainer默认会缓存attention,加上gradient checkpointing能省不少。建议先试试单卡加4bit量化,batch size降到1,确认能跑再调大,另外检查下dataloader的num_workers是不是设太高了,有时候这玩意也会偷显存。
说实话看到这个我第一反应是batch size 4在两张3090上确实不算大,但7B模型光fp16加载就要14G左右,加上LoRA的梯度和优化器状态,单卡24G其实挺紧的。你试了bitsandbytes 4bit还炸的话,建议先确认一下是不是量化加载的代码写对了——有时候没指定device_map或者没加bnb_4bit_compute_dtype,其实还是按默认精度跑的。
gradient checkpointing确实该开,直接在TrainingArguments里设gradient_checkpointing=True就行,能省大概30%的显存,代价就是慢一点。另外你可以试试把模型用accelerate的device_map="auto"拆到两张卡上,这样每张卡只放一半参数,再配合4bit量化,应该能跑起来。
dataloader方面,除了batch size,输入序列长度也很关键,如果文本太长可以尝试max_length=512甚至256,很多开源仓库默认开到1024以上,7B模型根本扛不住。Hugging Face Trainer里的per_device_eval_batch_size有时候也会被默认设得太大,建议手动调低。
最后一个小技巧:检查一下是不是安装的bitsandbytes版本和CUDA不匹配,我之前因为这个踩过坑,加载量化模型直接OOM,换了个版本就正常了。
说实话7B模型用LoRA两张3090肯定能跑,你batch size设4确实偏大了,先降到1试试。gradient checkpointing直接在Trainer里传gradient_checkpointing=True就行,能省不少显存。另外bitsandbytes的4bit量化有时候和特定transformers版本不兼容,建议换个版本或者直接用8bit试试。还有检查下是不是把整个模型都加载到单卡上了,用device_map="auto"可以自动分到多卡。
老实讲,7B模型在两张3090上用LoRA按说确实是够的,但你batch size设4其实挺激进的,尤其是序列长度如果超过512或者1024,那显存压力直接拉满。我自己的经验是,7B模型4bit量化后单卡大概能撑到batch size 2到4之间,但要是双卡没做模型并行或者张量并行,光靠数据并行其实每张卡还是得重复加载完整模型,加上优化器状态和梯度,24G很容易就爆了。
gradient checkpointing确实是个好东西,你可以在Trainer里直接传gradient_checkpointing_enabled=True,或者手动在模型上调用model.gradient_checkpointing_enable(),它本质是牺牲计算换显存,对于微调场景特别管用。另外你提到的bitsandbytes,我建议检查下是不是正确加载了load_in_4bit=True,以及有没有设置bnb_4bit_use_double_quant,这俩组合能再省一截显存。
至于Hugging Face Trainer,它默认会启用一些配置比如ddp_find_unused_parameters=False,但最坑的是它可能会自动做梯度累积或者混合精度,如果不显式设置fp16=True或bf16=True,默认的float32算起来显存直接翻倍。你可以试试把batch size降到1,开梯度累积到4步,加上gradient checkpointing,再配合4bit量化,基本能稳在3090上跑。
还有个小技巧,如果模型加载炸了,先用torch.cuda.empty_cache()清下缓存,有时候是之前跑残留的碎片占着。实在不行就考虑ZeRO-3或者DeepSpeed,不过感觉你这个问题主要还是batch size和精度没调好,先别急着上多卡分布式那套。
batch size 4不算大,但7B模型不量化的话24G确实吃紧,试试gradient checkpointing加上4bit量化,应该能稳住。
batch size 4对7B模型确实有点大,试试gradient checkpointing加4bit量化,两张卡用device_map='auto'自动分配。
7B模型用两张3090跑LoRA理论上没问题,但batch size设4确实偏大,尤其如果序列长度超过512的话。你先试试batch size降到1,同时把gradient checkpointing打开,在Trainer里设gradient_checkpointing_enabled=True就行。另外bitsandbytes的4bit量化要注意加载时加load_in_4bit=True和bnb_4bit_compute_dtype=torch.float16,不然默认精度反而更吃显存。如果还炸,检查下是不是tokenizer的max_length没设对,模型默认会按最大长度填充。
两张3090跑7B LoRA按理说是够的,batch size设4其实不算大,但关键是你得先确认一下有没有把模型的tokenizer和padding搞太长了,有时候默认的max length一设成2048或者4096,显存直接翻倍。gradient checkpointing你可以直接在Trainer里加个gradient_checkpointing=True,能省不少显存,另外bitsandbytes的4bit量化如果还炸,试试先加载模型时把device_map="auto"加上,让模型自动分配到两张卡上。你可以先跑一个极小的batch(比如1)看看能不能加载成功,逐步排查是模型本身的问题还是dataloader的锅。
batch size 4对7B模型确实大了,先降到1试试,gradient checkpointing在Trainer里设args.gradient_checkpointing=True就行。
batch size 4对7B模型确实偏大,先降到1试试,gradient checkpointing在Trainer里设--gradient_checkpointing就行。
两张3090跑7B LoRA按理说够的,batch size设4对24G显存确实偏大,先试着降到1或者2看看。gradient checkpointing在Hugging Face的Trainer里直接设gradient_checkpointing=True就行,能省不少显存。另外bitsandbytes的4bit量化有时候会和某些版本的transformers冲突,建议检查下版本对不对,或者直接用load_in_4bit=True参数加载模型。如果还是炸,试试把模型用device_map="auto"分到两张卡上,accelerate库会自动处理。