最近在试着用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 条讲真两张3090跑7B LoRA完全够,问题大概率出在加载基座模型时没开低精度或者device_map没设好。你可以试试load_in_4bit=True加上device_map="auto",然后batch size先调到1看能不能跑通,能跑再往上加。gradient checkpointing一定要开,Trainer里直接传gradient_checkpointing=True就行,能省不少显存。另外dataloader那边num_workers设成0试试,有时候多进程加载反而会吃显存。我之前也卡在这步,最后发现是transformers版本太旧导致量化参数没生效,升级一下就好了。
说实话你这配置跑7B LoRA是够的,问题大概率出在加载阶段而不是训练阶段。3090单卡24G其实能塞下7B的4bit模型,但如果你直接from_pretrained加载原始权重再转量化,峰值显存会瞬间爆掉——正确做法是加载时就指定load_in_4bit=True,让bitsandbytes直接按量化格式读权重,别先加载fp16再转换。
另外batch size=4在单卡上确实偏激进,LoRA虽然省了梯度但激活值照样吃显存,尤其序列长度超过512的话。你可以先试batch size=1,配合gradient_accumulation_steps=8,效果等同batch size=8但显存占用能降一个量级。gradient checkpointing肯定要开,model.gradient_checkpointing_enable()一行代码的事,能省差不多一半激活显存,代价是慢15%左右,但总比OOM强。
还有个小坑,Hugging Face Trainer默认会计算eval loss,如果你没关prediction_loss_only,评估阶段也会额外占显存。建议把evaluation_strategy设成"no",等训练完再单独跑验证。多卡的话device_map="auto"配合accelerate能自动分片,但3090没有NVLink,跨卡通信效率一般,不如先单卡调通再考虑。
最后检查下你的bitsandbytes版本,老版本对LLaMA支持有bug,最好升到0.39以上。我之前也是被这个坑过,换成4bit后显存占用直接从23G降到9G,跑起来完全没问题。先按这个思路调,应该能解决。
7B模型光fp16权重就要14G,两张3090单卡24G看着够,但LoRA的梯度和优化器状态才是大头,batch size 4在7B上确实有点激进。建议先把batch size降到1,然后开gradient checkpointing,代码里model.gradient_checkpointing_enable()就行,显存能省40%左右。bitsandbytes那个4bit加载其实还有坑,得配合bnb_4bit_compute_dtype=torch.float16用,不然反量化的时候照样爆。另外Hugging Face Trainer默认会算eval loss,如果没设evaluation_strategy="no",那评估阶段也会占不少显存,先关掉试试看。
gradient checkpointing开了能省不少,但batch size 4在3090上跑7B确实有点紧,试试1或者2。
大概率是加载时峰值爆了,先把batch size降到1,加上gradient checkpointing和8bit优化器,应该能稳。
你这配置跑7B绝对够,问题八成出在batch size和默认参数上,gradient checkpointing开了能省一大半显存。
7B模型加载时本身就要占14G左右,两张3090单卡跑batch size 4确实会爆,建议先用batch size 1试试,能跑通再往上加。gradient checkpointing在Trainer里直接传gradient_checkpointing=True就行,但记得同时把model的use_cache关掉,不然会报错。另外LoRA加4bit量化的话,记得用bitsandbytes的配置文件单独设置一下,别直接load_in_4bit=True,有时候是transformers版本和它不兼容导致的。你试试看单卡batch size 1加梯度累积,应该能稳下来。
7B模型光fp16权重就14G,两张3090单卡加载肯定够呛,batch size 4在LoRA下确实偏大,先降到1试试。gradient checkpointing在Trainer里直接设gradient_checkpointing=True就行,但记得同时把model.gradient_checkpointing_enable()调一下。4bit量化配LoRA确实能省不少,但你要是用了seq length特别长的数据,照样会炸,检查下是不是max length设太大了。还有个小坑,bitsandbytes在3090上偶尔会有兼容问题,换个0.39版本试试。
3090跑7B按理够,先把batch size降到1试试,gradient checkpointing加上能省一半显存。
3090跑7B LoRA完全够,先试试gradient checkpointing加batch size调到1,大概率能救回来。
试试把batch size降到1,开gradient checkpointing,LoRA用4bit加载模型基本就能稳。
如果只是加载模型就爆的话,大概率不是batch size的问题,7B模型fp16光权重就要14G,3090单卡能放但加上优化器状态和激活值就悬了。你试试先不开LoRA,纯加载模型看显存占用,再一步步加组件排查。gradient checkpointing在Trainer里直接设gradient_checkpointing=True就行,但注意要和torch.compile或者某些自定义模型结构兼容。另外4bit量化后一定要把torch_dtype设成float16,不然bitsandbytes会自动用fp32,显存直接翻倍。我自己的经验是两张3090跑7B LoRA,batch size 2加梯度累积,稳得很。
你batch size设4确实偏大了,3090单卡跑7B LoRA一般得开到1或者2,先把gradient checkpointing打开试试。
8的batchsize太大,7B模型用LoRA也得开gradient checkpointing,4bit量化后还是得配batchsize=1慢慢试。
说实话7B模型加载到一张3090上光权重fp16就得占14G左右,加上优化器状态、梯度和中间激活值,单卡24G确实很紧张,但两张卡一起跑应该没问题。你batch size=4对于7B来说不算大,问题大概率出在没开gradient checkpointing——这个能在不牺牲太多速度的情况下把激活内存砍掉一大半,用Trainer的话直接传gradient_checkpointing=True就行。另外bitsandbytes的4bit量化如果还炸,看看是不是没把load_in_4bit=True和bnb_4bit_compute_dtype=torch.float16配合好,有时候默认的fp32计算会偷偷吃掉显存。还有个小坑是torch.compile在某些版本下会额外占显存,你要是开了就先关掉试试。最稳的做法是把模型用device_map="auto"加载,让accelerate自动分配到两张卡上,数据加载用num_workers=4和pin_memory=True能省点CPU内存间接压力。我自己的经验是LoRA微调7B,单张3090开4bit+gradient checkpointing,batch size=2都能跑起来,你双卡肯定更宽裕,建议先从关闭一切花哨功能开始,逐步加回来看哪步爆的。实在不行试试optim="adamw_8bit",优化器状态是显存大头,这个能省不少。
看到你说两张3090还OOM,我第一反应是肯定哪里配置没对齐,这个卡跑7B LoRA是绰绰有余的。我之前用单张4090(24G)都能跑13B的4bit微调,batch size还比你大,所以问题大概率不在显存容量本身。
你提到加载模型就炸,那得先确认是不是transformers版本太新导致的显存预分配问题,有些版本默认会缓存整个模型的全精度权重到GPU上,即使开了4bit也照样爆。建议检查一下model.config里torch_dtype是不是float16,同时显式调用model.to('cuda')而不是依赖accelerate自动分配。
batch size=4对于LoRA来说确实偏大,尤其如果你没开gradient accumulation的话,24G两张卡其实每张只分到12G,7B模型即使4bit也有4-5G的权重占用,加上激活值和优化器状态,很容易顶满。我一般用batch size=1或2,配合gradient accumulation步数=4或8,效果一样但显存压力小很多。
gradient checkpointing肯定要开,在Trainer里传gradient_checkpointing=True就行,但注意开了之后要把model.gradient_checkpointing_enable()也手动调一下,有些版本不自动生效。另外你提到bitsandbytes,建议用load_in_4bit加bnb_4bit_use_double_quant=True,同时设置bnb_4bit_quant_type='nf4',这样能再挤出一部分空间。
还有个小坑,Trainer的默认per_device_eval_batch_size如果没改,可能跟训练batch size一样大,验证阶段也会爆。我通常会把eval batch size设成1,或者直接用batch_eval_metrics聚合。最后,如果还不行,试试torch.cuda.empty_cache()放在每个epoch开头,有时候碎片化也会导致假性OOM。
7B上3090单卡都够呛,你batch size开4肯定炸,先降到1试试。
说实话两张3090跑7B LoRA完全够,问题大概率不是显存绝对容量不够,而是加载时瞬间峰值爆了。建议先试试把模型加载改成device_map="auto"配合low_cpu_mem_usage=True,然后训练时显式关掉cache,再开gradient_checkpointing=True,这样能省不少。还有个坑是dataloader的num_workers别开太高,有时候数据预取的临时显存也会叠加,batch size降到2先跑通再往上调。如果还炸,就把bitsandbytes换成8bit试试,4bit在某些版本下反而有兼容性问题。
7B模型用LoRA按理说双3090应该够,但你先确认下是不是加载基座模型时就直接FP16全量进去了,那光权重就14G,加上激活值肯定爆。batch size=4在24G卡上确实偏大,建议先减到1或2试试,同时把gradient checkpointing打开,Trainer里直接传gradient_checkpointing=True就行,能省不少显存。bitsandbytes如果你用的是4bit的QLoRA,记得加载时也要设置device_map="auto",不然它还是会默认全塞进单卡。另外你检查下是不是tokenizer的padding把序列长度拉太长了,有时候这玩意比batch size更吃显存。
7B模型光fp16权重加载就要14G,两张3090单卡跑确实勉强,但batch size=4不是主要问题,LoRA本身显存大头在激活值。建议先开gradient checkpointing,在Trainer里设gradient_checkpointing=True就行,能省一半左右显存。另外bitsandbytes别用4bit,试试8bit加load_in_8bit=True,同时把torch_dtype=torch.float16加上,加载时用device_map="auto"让模型自动分到两卡。还有,dataloader的num_workers别设太高,有时候CPU内存爆了也会引发OOM假象。我之前用单卡24G跑7B,LoRA+8bit+gradient checkpointing+batch size=1,显存峰值大概17G,你可以参考下这个配置。