最近在试着用LoRA微调llama3-8B,显卡是3090(24G),batch size调到2,gradient accumulation设了8,显存占用大概16G左右。但跑一个epoch要差不多10个小时,感觉不太对劲。我看网上有人用同样配置微调13B都没这么慢。我的数据集大概5万条,max length设了2048,也试过用flash-attention和deepspeed stage2,但速度提升不明显。是不是我哪里配置有问题?还是说这个速度其实是正常的,只是我预期太高了?求有经验的大佬指点一下,或者有什么优化方向可以尝试的?顺便问下,用QLoRA会不会快一些?谢谢!
用LoRA微调7B模型,显存够但训练速度慢得离谱正常吗?
全部回复
共 111 条说实话这个速度确实偏慢了,但问题可能不在LoRA本身。5万条数据、2048长度,单卡3090跑8B,理论上一个epoch应该在3-4小时左右才算合理。你试了flash-attention和deepspeed但提升不明显,我怀疑瓶颈根本不在计算上,而是数据加载或者CPU预处理拖了后腿。建议先检查下dataloader的num_workers是不是设成0了,或者试试把数据集预处理成tokenized的memmap格式,能省掉每次迭代的tokenize开销。另外你gradient accumulation设8,但batch size才2,等效batch=16,对8B模型来说这个配置下显存利用率其实不高,可以试试直接加大batch size到4,然后减少accumulation步数,有时候反而更快。QLoRA的话,4bit量化后显存占用会更低,但速度大概率不会变快,甚至因为反量化操作会略微变慢,它主要优势是能跑更大的模型。我之前遇到过类似情况,最后发现是transformers版本和flash-attn不兼容,导致attention根本没走flash路径,你查下日志里有没有相关警告。还有个冷门但很有效的点:检查下你的CPU内存是不是爆了,swap频繁的话训练会突然卡成PPT。最后建议用nsys或py-spy做个profile,看看每步到底卡在哪个环节,比盲调参数靠谱得多。
说实话这速度不太正常,我拿3090跑llama3-8B lora,5万条数据max length 2048,一个epoch大概四五个小时就完事了。你试试把packing打开,还有检查下是不是dataloader的num_workers设成0了,数据加载卡住很常见。另外QLoRA不会更快,反而因为量化多一步转换,单步速度还可能更慢,但能省显存调大batch。
我怀疑你可能是seq长度太长导致计算量上去了,试试把max length砍到1024看速度差多少,如果差距巨大那就是长度瓶颈。还有deepspeed stage2对单卡lora意义不大,不如直接关掉用原生hf trainer,有时候这些框架反而拖慢速度。你要是实在找不到原因,可以看看是不是CPU内存瓶颈,把数据集先缓存成arrow格式会好很多。
顺便说下,网上说13B跑得快可能是他们用了更短的seq或者数据量没你的大,光看epoch时间不准,你算下每秒处理多少条样本更靠谱。我建议你开个profiler看下gpu利用率,如果经常掉到80%以下那就是数据管线问题,不是模型本身慢。
说实话这个速度虽然慢,但也没离谱到不正常的地步。5万条数据、2048长度,单卡3090跑llama3-8B,一个epoch十小时换算下来每秒也就处理1.4条样本,考虑到attention计算量随序列长度二次增长,这个数字其实挺符合预期的。你看到网上13B跑得快的帖子,大概率人家数据集短或者max length没拉到2048,很多人用512甚至256,速度能差出四到八倍。flash-attention和deepspeed stage2在这类小规模场景下收益确实有限,瓶颈主要在数据吞吐和kernel launch上,建议先看看你的gpu利用率是不是一直跑不满,如果经常掉到50%以下,那多半是数据加载或预处理成了瓶颈,试试把num_workers调高、用dataloader预取,或者干脆把tokenize后的数据缓存成二进制格式。QLoRA理论上能省显存但不会明显提速,因为4bit量化反而会增加反量化计算开销,除非你同时把batch size翻倍,否则大概率更慢。真要想快,最直接的还是砍max length到1024或512,或者先用子集跑通流程确认代码没别的隐藏问题,另外检查下是不是在跑验证集时没关gradient,那种情况时间会白白翻倍。
5万条2048长度,10个小时一个epoch其实不算离谱,3090的算力摆在那呢。你看到网上13B快的,多半是序列长度短或者数据集小,纯比时长没意义。QLoRA不会变快,4bit量化反而可能更慢,它只是省显存。建议先看看数据是不是真的都需要2048,把平均长度降下来可能收益最大。另外检查下是不是有CPU瓶颈,比如tokenize或者数据加载没做好,有时候瓶颈根本不在GPU上。
说实话你这速度有点离谱了,我拿3090跑llama2-7B lora,5万条数据max length 1024大概也就3-4小时一个epoch。你试试把max length砍到1024看看,2048对8B来说token处理量翻倍,而且长序列下attention计算是平方级增长,flash-attention对这种长度提升有限。另外确认下你是不是把gradient checkpointing开了,这个能省不少显存但会拖慢速度,如果显存够用关掉反而更快。QLoRA不会更快,4bit量化反而可能因为反量化开销更慢,但能省显存让你把batch size调大,整体吞吐可能持平。建议先看一眼nvidia-smi,确认是不是跑在PCIe带宽瓶颈上,有时候数据加载预处理会成为隐藏瓶颈。
这个速度确实有点离谱了,我拿同样的卡跑llama3-8B,5万条数据max length 2048,LoRA单卡大概4-5小时一个epoch。你试试把max length砍到1024看看,大部分数据用不到那么长,能快一半以上。另外flash-attention装了但没生效的话,损失很大,建议确认下是不是真的import成功了。QLoRA就别指望提速了,它省的是显存不是算力,反而因为反量化多了开销会更慢。
5万条跑10小时确实偏慢,先查查dataloader的num_workers是不是设太低了。
5万条数据、max length 2048,一个epoch十小时其实不算特别离谱,但确实偏慢了,尤其你显存才占16G,说明还有余量没吃满。我怀疑瓶颈主要出在数据加载和attention实现上,你可以先检查一下dataloader的num_workers是不是设得太小,或者数据预处理有没有在训练时实时做tokenize,那样会非常拖速度。另外flash-attention要真正生效得确认装对了版本并且模型代码里实际调用了,很多人装了但没启用。gradient accumulation设8意味着你实际等效batch是16,单步forward次数多,如果GPU利用率一直上不去,那基本就是IO或者CPU在拖后腿。QLoRA理论上不会更快,它省的是显存不是算力,反而因为要反量化可能还稍慢一点,但能让你把batch size开大来换吞吐。建议先用小样本跑几百步测一下吞吐,再逐步调num_workers和pin_memory,通常能改善不少。
5万条数据、max length 2048,一个epoch 10小时其实不算离谱,但确实偏慢。你检查下dataloader的num_workers是不是设太低了,还有gradient checkpointing有没有开,这两个影响挺大的。另外3090不支持bf16原生加速,试试fp16混合精度,有时候能快不少。QLoRA主要省显存,速度不一定更快,你显存够的话没必要换。
5万条数据、max length 2048,一个epoch十小时其实不算离谱,关键看你tokens/sec多少。3090跑8B LoRA,bs=2加ga=8等效bs也就16,吞吐上不去很正常,flash-attn对LoRA训练提升本来就有限,瓶颈往往在数据加载和attention之外的层。建议先测一下实际吞吐,再检查dataloader的num_workers是不是设太低了。QLoRA能省显存但不会更快,有时反而更慢,因为多了反量化开销,你显存够就没必要换。
5万条跑10小时确实偏慢,试试降max length到1024,长尾样本很拖速度。QLoRA会快但也就快一点,瓶颈可能不在精度上。