梯度累积并非中性的速度调节器:LoRA 实测对比
Qwen3-1.7B + LoRA 在 T4 与 L4 上测试表明,同样有效 batch 下不同梯度累积策略训练耗时差异…
在 LoRA 微调中,有效 batch size(effective batch)相同并不意味训练时间也相同。Reddit 用户 traceml-ai 在 r/MachineLearning 上分享的实测显示,在 Qwen3-1.7B 模型配合 TRL 与 LoRA 训练时,把有效 batch 固定为 4,但分别采用 1×4、2×2 与 4×1 三种梯度累积组合,三者耗时在 T4 与 L4 上均出现明显差异。
实验设置
- 模型:Qwen3-1.7B
- 微调方式:LoRA(低秩适配)
- 训练流程:TRL Trainer,共 100 次 optimizer 更新
- 固定变量:模型、数据、序列长度、精度与随机种子
- 硬件:单卡 T4、单卡 L4,分别独立测试
- 计时工具:TraceML 的 Hugging Face 回调,用于逐步与分阶段耗时测量
测试不涉及多卡通信,因此观察到的差异主要来自单卡前向与反向计算本身。
主要耗时结果
在 100 次 optimizer 更新内的端到端耗时(秒,越低越好):
- T4
- 1×4:287.6 s
- 2×2:258.8 s
- 4×1:238.2 s
- L4
- 1×4:213.02 s
- 2×2:119.47 s
- 4×1:124.76 s
在 T4 上,4×1 比 1×4 快约 17%;在 L4 上,差距扩大到约 41%。L4 上 2×2 略快于 4×1,说明物理 batch 增大时吞吐提升并非线性。
原因分析
实验者认为,关键在于「有效 batch」是优化层面的旋钮,而「物理 batch」决定了 GPU 实际看到的工作形状:
- 1×4:四次较小的前向/反向后做一次 optimizer 更新
- 4×1:一次较大的前向/反向后做一次 optimizer 更新
样例到达 optimizer 的总量一致,但 GPU 实际承担的工作并不相同。多次小批次的 kernel 调度、启动开销与显存 tiling 模式都会影响吞吐。耗时差异集中在反复执行的前向与反向阶段,optimizer 本身的耗时几乎不变。
需要注意的是,该实验并未将 kernel 形态、tiling 策略、launch overhead 等原因逐项拆开,只能说明现象层面有显著差异。
实践建议
原帖总结出两点经验供 LoRA 微调实践者参考:
- 把「有效 batch」视作控制优化行为的参数;
- 把「物理 batch + 梯度累积步数」视作同时影响显存占用与速度的参数。
Hugging Face 官方文档亦指出,梯度累积本身并不比直接使用更大的物理 batch 提升吞吐;这与本次实验的结论方向一致。
实操建议:先尝试显存能稳定容纳的最大物理 batch,再在该值附近进行几种组合实测,再做最终选择。
原文附带可复现的 Colab Notebook,感兴趣读者可自行验证。
