使用 PyTorch DDP、Accelerate 和 Transformers Trainer 进行分布式训练

Hugging Face 详细阐述了在 PyTorch 中实现分布式训练的三层抽象,从原生分布式数据并行(DDP)到 Accelerate 库,最终到 Transformers Trainer API。这一演进使开发者能够在对训练循环的细粒度控制和分布式设置的高级自动化之间进行选择。

原生 PyTorch 分布式数据并行(DDP)

PyTorch DDP 能够在多个 GPU 上进行训练,无论这些 GPU 位于单台机器(多 GPU)还是跨多台机器(多节点)。它的工作方式是将模型复制到每个 GPU 上,并在 loss.backward() 调用期间对所有副本的梯度进行平均,以确保各设备之间的权重保持一致。

  • 进程组设置:开发者必须定义 setupcleanup 函数来初始化和销毁进程组,并指定用于通信的 MASTER_ADDRMASTER_PORT
  • 模型包装:模型必须使用 DistributedDataParallel(DDP)模块进行包装,并且优化器必须基于该包装后的模型声明,以确保梯度正确计算。
  • 执行:脚本通常使用 torchrun 命令行模块启动,需指定节点数量和每个节点的进程数。

使用 🤗 Accelerate 简化分布式

Accelerate 是 pytorch.distributed 的轻量包装器,能够让相同的代码在单 GPU、多 GPU 或 TPU 上运行,只需进行最小的修改。它消除了手动进程组设置的需求,并简化了设备放置。

技术改进

Accelerate 引入了 Accelerator 类,通过一次调用 accelerator.prepare() 来处理模型、优化器和数据加载器的分布。这取代了手动的 .to(rank) 调用和 DDP 包装。

除了简化之外,Accelerate 通过自定义采样器提升了内存效率。它不再在各设备上创建多个完整的数据加载器副本,而是确保内存中仅保留原始数据集的一个完整拷贝,并在可用节点之间划分数据子集。这避免了在超大数据集上训练时出现内存爆炸。

Notebook 集成

对于在 Jupyter Notebook 中工作的用户,Accelerate 提供了 notebook_launcher 实用工具。通过传入训练函数和进程数量,即可直接在 Notebook 中触发多 GPU 训练。

通过 🤗 Trainer 实现高级抽象

Transformers 的 Trainer API 提供了最高层次的抽象,几乎消除了与分布式训练相关的所有样板代码。它会自动处理底层的分布式逻辑,无需用户编写显式的训练循环。

要使用 Trainer,开发者需要定义 TrainingArguments 来管理超参数,并可以子类化 Trainer 实现自定义的 compute_loss 函数。随后,Trainer 会自动在分布式系统中管理训练和评估过程。与 Accelerate 示例类似,Trainer 也可以与 notebook_launcher 集成,以便在交互式环境中快速实验。

Sources