最近在试着用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模型,显存够但训练速度慢得离谱正常吗?
全部回复
共 118 条说实话这个速度确实偏慢了,但问题可能不在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会快但也就快一点,瓶颈可能不在精度上。
5万条数据、max length 2048,一个epoch十小时其实不算离谱,瓶颈大概率在attention计算和sequence长度上,不是显存。你batch size才2,gradient accumulation又设8,等于实际每步只过2条样本,GPU利用率估计上不去。建议试试把batch size拉到8或16配合梯度检查点,再把max length降到1024试试,很多时候长尾样本占了大头但贡献很小。QLoRA主要省显存,你显存没吃满的话速度提升很有限,反而量化反量化可能还多花时间。
5万条数据跑一个epoch十小时确实偏慢了,我之前3090上跑3万条也就四个多小时。你试试把gradient checkpointing关了,LoRA本来就省显存,开了反而拖速度。另外max length 2048如果大部分样本没这么长,建议按实际分布截断,能省不少计算。QLoRA量化后前向会慢一点,但显存省下来可以拉大batch,整体不一定更快,得实测。
5万条数据、max length 2048,一个epoch跑10小时确实偏慢了,感觉瓶颈可能不在显存而是在数据加载或者sequence packing上。你检查过dataloader的num_workers没?设太小的话GPU经常在等数据,利用率上不去。另外QLoRA主要省显存,速度不一定比LoRA快,反而多了量化反量化的开销,你显存够就别折腾了。建议先nvidia-smi盯着看GPU利用率,如果一直低于70%那基本就是数据管道拖后腿了。
5万条数据、max length 2048,一个epoch十小时其实不算特别离谱,但确实偏慢了。你batch size才2,梯度累积8,等于实际batch 16,3090跑8B LoRA这个吞吐差不多就这样,瓶颈大概率在数据加载和attention计算上。建议查下dataloader的num_workers是不是设太少了,还有试试packing把短样本拼起来,能省不少时间。QLoRA主要是省显存,速度不一定更快,有时候反而因为反量化更慢,你显存够的话没必要换。
5万条跑10小时其实还好,瓶颈多半在数据加载,试试把dataloader workers调大点。
5万条数据、max length 2048,一个epoch 10小时其实不算特别离谱,但确实偏慢了。你算一下,5万条除以batch size 2再除以grad accumulation 8,差不多要跑3125个step,每个step如果3-4秒,加起来也就3小时左右,所以10小时说明单步耗时可能在10秒以上,这就有点问题了。我怀疑瓶颈不一定在算力上,可能是在数据加载那块,你可以看看dataloader的num_workers是不是设得太小,或者数据预处理有没有在训练时动态做tokenize,那个特别拖速度。另外3090是不支持bf16原生加速的,如果你用的bf16可能反而比fp16慢,试试切回fp16加scaler看看。flash-attention要确认真的生效了,有时候装了但没走对路径,可以看下日志里有没有相关提示。QLoRA主要省显存,速度上不一定比LoRA快,因为多了反量化开销,你显存够的话没必要换。建议先用profiler跑几百步定位一下到底时间花在哪,别盲目调参。
试试把max length砍到1024,你这多半是padding太多拖的,QLoRA省显存但速度提升有限。