【分布式训练(6)】深入理解多卡训练时 training steps, epoch 的相关概念
【分布式训练 debug】VS Code Debug 技巧:launch.json实用参数
【分布式训练(2)】深入理解 DeepSpeed 的 ZeRO 内存优化策略 (三阶段的区别)
【分布式训练(3)】accelerator + deepspeed debug 报错 “Timed out waiting for debuggee to spawn“ 解决方法✅
【分布式训练(4)】accelerator.sync_gradients 和 checkpointing 深入理解
【分布式训练(5)】无法 kill PID?如何 kill 休眠中的 GPU 占用进程
概念
不同于单卡训练,注意要考虑 Batch Size 是总的还是每张 GPU 的。
概念 | 定义 | 关系与说明 |
---|---|---|
Train Batch Size | 每次迭代用于训练模型的数据样本总数。 | 总批量大小,可以分布在多个GPU上。 |
Batch Size per GPU | 每个GPU上每次迭代用于训练模型的数据样本数。 | 如果使用多个GPU,train batch size = (batch size per GPU) × (GPU数量) |
Step | 一次前向传播和一次反向传播的完整过程。 | 每次参数更新,一个train batch size包含多个steps(如果使用梯度累积)。 |
Epoch | 模型完整地在训练集上训练一遍。 | 一个epoch包含多个steps,具体数量取决于train batch size。 |
例如,假设我们有以下情况:
- Train Batch Size: 1000
- Batch Size per GPU: 250
- GPU数量: 4
那么在一个epoch中:
- 每个GPU将处理250个样本的批量。
- 总共有1000个样本被用来更新模型一次,这意味着在不考虑最后一个不完整的批量的情况下,每个epoch包含1000个step。
- 如果使用梯度累积,可能需要多个step的梯度累积起来再进行一次参数更新。
这样,我们就可以在多GPU环境中更有效地利用硬件资源,加速训练过程。同时,通过调整train batch size和batch size per GPU,我们可以控制每次更新模型时使用的数据量,进而影响模型训练的稳定性和收敛速度。
相关分布式训练代码理解
文本以 flux 的微调训练代码为例 https://github.com/XLabs-AI/x-flux/blob/main/train_flux_deepspeed.py
dataloader 部分
train_dataloader = loader(**args.data_config)
# Scheduler and math around the number of training steps.
overrode_max_train_steps = False
num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps)
- train_dataloader 是一个数据加载器,用于在训练过程中按批次加载训练数据。
- 这个 dataloader 会有每次加载的数据数量:batch size。
- 以及总数据集(文图对)中图像/文本的总数量:len(train_dataloader) 。
- args.gradient_accumulation_steps 是一个超参数,表示在**进行一次参数更新之前要累积的梯度步数。**也就是说,如果这个值为 k,那么模型将在 k 个批次上计算梯度,然后再进行一次更新。
- num_update_steps_per_epoch = math.ceil(len(train_dataloader) / args.gradient_accumulation_steps) 计算出在一个 epoch 中进行的更新步骤数。这个值是通过将总批次数除以每次更新所需的批次数来获得的。
args.num_train_epochs = math.ceil(args.max_train_steps / num_update_steps_per_epoch)
通常情况下,像 args.num_train_epochs 这样的超参数应该在训练开始之前被设定为固定值,而不是在训练过程中被动态计算和赋值。并且这行代码还出现了两次一模一样的,所以合理怀疑这里写的是有点问题。
total_batch_size = args.train_batch_size * accelerator.num_processes * args.gradient_accumulation_steps
总的 batch size = 每张 GPU 的 train_batch_size x 进程数量(GPU 数量) x 梯度累计的步数
loss 回传部分
# Gather the losses across all processes for logging (if we use distributed training).
avg_loss = accelerator.gather(loss.repeat(args.train_batch_size)).mean()
train_loss += avg_loss.item() / args.gradient_accumulation_steps
- 在分布式训练中,模型可能在多个 GPU 或多个机器上并行训练。每个进程(或设备)会计算自己的损失值。为了进行有效的监控和记录,通常需要将所有进程的损失值汇总到主进程中。
- loss.repeat(args.train_batch_size):将当前进程计算的损失值 loss 重复 args.train_batch_size 次。这样做的目的是为了确保在后续的汇总过程中,每个样本的损失都能被正确地考虑。
- 例如,如果当前进程的批次大小是 8,而 args.train_batch_size 是 32,那么 loss 将被重复 4 次,以便在汇总时能够反映出整个批次的损失。
- accelerator.gather(…):accelerator.gather 是一个用于收集所有进程的张量的函数。
- 在分布式训练中,每个进程会计算自己的损失,使用 gather 可以将这些损失值从所有进程收集到主进程。
- 这使得主进程能够访问所有进程的损失值,以便进行后续的处理和记录。
- .mean():在收集到所有损失值后,使用 .mean() 计算所有进程损失的平均值。这是因为在分布式训练中,通常希望得到一个全局的损失值,以便更好地监控训练过程。
- train_loss += avg_loss.item() / args.gradient_accumulation_steps:
- 最后,将计算得到的平均损失 avg_loss 除以 args.gradient_accumulation_steps,并累加到 train_loss 中。
- 这是因为在使用梯度累积时,损失是累积的,实际的训练损失需要考虑到累积的步数。
- 通过这种方式,train_loss 将反映出在当前梯度累积步骤中的平均损失。
原文地址:https://blog.csdn.net/weixin_44212848/article/details/142957625
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!