2024-09-13
深度学习
00

目录

多机多卡深度学习训练:Python torch.distributed.launch、torchrun、accelerate 和 deepspeed 对比解析
1. Python -m torch.distributed.launch
特点与功能
优势
底层架构
NCCL (NVIDIA Collective Communications Library) 详解
使用方法
每个机器显卡数量不同的情况
交互性
2. torchrun
特点与功能
优势
底层架构
使用方法
交互性
3. accelerate
特点与功能
优势
底层架构
使用方法1
使用方法2
accelerate + DeepSpeed
deepspeed_config 的配置方法
示例配置:
常见的 DeepSpeed 配置参数:
ZeRO-3
配置 ZeRO-3 的步骤
示例 deepspeed_config.json:
交互性
4. DeepSpeed
特点与功能
优势
底层架构
使用方法
多机多卡训练步骤
交互性
工具对比
工具的交互使用
torchrun 与 DeepSpeed 的结合
accelerate 与 DeepSpeed 的结合
torchrun 与 accelerate
工具选择指南
分布式训练的最佳实践
总结

多机多卡深度学习训练:Python torch.distributed.launchtorchrunacceleratedeepspeed 对比解析

随着深度学习模型规模的迅速增长,单机单卡的计算能力往往不足以满足训练需求。在多机多卡的环境中,分布式训练技术成为了加速训练的关键。本文将从工具角度出发,探讨几种常用的分布式训练工具:python -m torch.distributed.launchtorchrunacceleratedeepspeed,分析它们的特点、优势、底层架构、如何使用以及是否可以交互使用。类似的还有Horovod、Ray Train,这里不介绍。


1. Python -m torch.distributed.launch

特点与功能

torch.distributed.launch 是 PyTorch 提供的原生分布式训练工具。它主要用于管理多机多卡的训练任务,通过显式启动多个训练进程,每个进程对应一张 GPU。

优势

  • 简单易用:与 PyTorch 框架无缝集成,直接通过命令行执行。
  • 支持多种后端:可以选择使用 NCCL(推荐用于 GPU)或 Gloo(用于 CPU 或网络较差的环境)。
  • 灵活性强:支持多机多卡,以及不同的拓扑结构和通信模式。

底层架构

torch.distributed.launch 基于 PyTorch 的分布式训练库 torch.distributed,每个进程都作为一个独立的 worker,通过后端(如 NCCL)进行通信。在多机训练时,通过传递主节点(master node)的地址和端口,使所有进程能够建立全局通信。

NCCL (NVIDIA Collective Communications Library) 详解

NCCL,全称为 NVIDIA Collective Communications Library,是由 NVIDIA 提供的一个专门为多 GPU 通信而设计的高性能库。它优化了 GPU 之间的数据传输,特别是在分布式深度学习训练中,NCCL 扮演着至关重要的角色。通过利用 NCCL,用户可以在多张 GPU 之间高效地进行数据并行化、模型并行化以及其他分布式操作。

NCCL 的主要任务是集体通信 (collective communication)。集体通信是一种涉及多个进程之间的同步数据传输方式,常用于分布式计算。在分布式深度学习中,常见的集体通信操作包括:

  1. All-Reduce:所有 GPU 之间聚合数据,并将结果同步回每个 GPU。通常用于梯度聚合。
  2. All-Gather:每个 GPU 向其他所有 GPU 发送自己的数据,并收集所有 GPU 的数据。
  3. Reduce-Scatter:数据先被聚合(reduce),然后按部分(scatter)分发给每个 GPU。
  4. Broadcast:将主进程的某一数据广播到其他所有进程。

高效的 GPU 通信

NCCL 专门为 NVIDIA GPU 设计,并充分利用了现代 GPU 硬件的特性,如 NVLink、InfiniBand 和 PCIe。它通过这些高速互连技术,极大地提高了多 GPU 间的数据传输速度,减少了数据传输的瓶颈。

  1. NVLink:一种专为 NVIDIA GPU 设计的高速互连技术,用于加速多 GPU 间的数据交换。
  2. InfiniBand:高带宽、低延迟的通信标准,广泛应用于大型数据中心和超算中,通过与 RDMA(Remote Direct Memory Access)结合,进一步提升分布式通信性能。
  3. PCIe:尽管带宽不如 NVLink 或 InfiniBand,但它是 GPU 与 CPU 或其他外设之间的主要数据交换通道。

GPU 原生支持

NCCL 最大的优势之一在于,它能够直接在 GPU 上执行通信操作,而无需将数据转移到 CPU 进行计算。这样可以最大程度上减少 CPU 的参与,提高了 GPU 的计算效率。

使用方法

要使用 torch.distributed.launch 进行分布式训练,需通过命令行启动:

bash
python -m torch.distributed.launch \ --nproc_per_node=4 \ --nnodes=2 \ --node_rank=0 \ --master_addr="192.168.1.1" \ --master_port=12345 \ train.py
  1. nproc_per_node:每个节点(机器)上启动的进程数,通常等于节点上的 GPU 数量。制在每个节点上同时运行的进程数。每个进程一般对应一个 GPU,从而充分利用机器的 GPU 资源。
  2. nnodes:总的节点(机器)数量。告诉 PyTorch 这次训练一共跨多少台机器进行。如果你要进行多节点的分布式训练,比如有 2 台机器参与训练,那么就会设置 --nnodes=2。
  3. node_rank:当前机器的排名(从 0 开始)。标识当前机器在整个集群中的序号,帮助 PyTorch 确定不同节点的角色。当有多台机器参与时,每个节点必须有一个唯一的 node_rank。例如,有 2 台机器,第一台机器设置 --node_rank=0,第二台机器设置 --node_rank=1。
  4. master_addrmaster_port:指定主节点的 IP 地址和端口。指定分布式训练中的主节点,所有其他节点会与这个节点通信来协调训练。在多节点训练中,所有节点需要知道谁是主节点,因此每个节点都要设置 --master_addr 为主节点的 IP 地址。

一个实际的例子:

假设你有 2 台机器参与训练,每台机器有 4 块 GPU。要启动分布式训练,第一台机器(Rank 0)上的命令如下:

bash
python -m torch.distributed.launch \ --nproc_per_node=4 \ --nnodes=2 \ --node_rank=0 \ --master_addr="192.168.1.1" \ --master_port=12345 \ train.py

而第二台机器(Rank 1)上的命令如下:

bash
python -m torch.distributed.launch \ --nproc_per_node=4 \ --nnodes=2 \ --node_rank=1 \ --master_addr="192.168.1.1" \ --master_port=12345 \ train.py

每个机器显卡数量不同的情况

每台机器的显卡数量可以不同,但是在使用 torch.distributed.launch 进行分布式训练时,配置会稍微复杂一些,具体要注意以下几点:

    1. 异构节点问题
    • 当每台机器上的 GPU 数量不一样时,你可以在启动训练时为每个节点单独指定 --nproc_per_node 参数。
    • 例如,假设机器 A 有 4 块 GPU,机器 B 只有 2 块 GPU,命令应该这样配置:
      • 机器 A(有 4 块 GPU):
        bash
        python -m torch.distributed.launch \ --nproc_per_node=4 \ --nnodes=2 \ --node_rank=0 \ --master_addr="192.168.1.1" \ --master_port=12345 \ train.py
      • 机器 B(有 2 块 GPU):
        bash
        python -m torch.distributed.launch \ --nproc_per_node=2 \ --nnodes=2 \ --node_rank=1 \ --master_addr="192.168.1.1" \ --master_port=12345 \ train.py
    1. 梯度同步与计算负载
    • 负载不均衡问题:当每台机器上的 GPU 数量不同,计算负载可能不均衡。例如,拥有更多 GPU 的机器每次训练会处理更多的数据,这可能导致训练速度变慢,因为训练需要等所有进程同步。
    • 梯度同步:在分布式训练中,每个进程都会同步计算梯度。如果有些进程处理的数据更多,可能会拖慢整个训练速度。因此,如果 GPU 数量不均衡,可能会导致效率降低。
    1. 推荐解决方案
    • 数据并行的调整:可以根据每台机器上 GPU 数量的差异,在数据并行时给每个进程分配不同大小的数据批次,确保负载均衡。这种情况下,显卡少的机器会处理较小的数据批次,显卡多的机器会处理较大数据批次,以减少性能差异对训练的影响。
    • 静态数据分配:一种简单的方式是手动调整代码,使每个节点处理的数据量与其计算能力相符,但这需要更多手动调整。

虽然每台机器的显卡数量可以不同,但在实际操作中需要考虑负载均衡和同步问题。如果机器之间的显卡差异很大,训练性能可能会受到影响,建议通过调整批量大小或其他方式来缓解不均衡带来的问题。

交互性

  • 不能直接交互使用,需要通过命令行启动。

2. torchrun

特点与功能

torchrun 是 PyTorch 1.9 引入的新的分布式训练启动器,它被设计为 torch.distributed.launch 的替代品。功能与 launch 基本相同,但更简洁和易用。

优势

  • 简化了命令行:与 torch.distributed.launch 相比,torchrun 省去了许多手动参数设置,自动处理了一些进程间的通信细节。
  • 更好的错误处理:增强了对分布式系统错误的捕获与报告。
  • 原生支持 PyTorch 的 Elastic 多进程:在任务中允许动态加入或移除进程,支持容错机制。

底层架构

launch 类似,torchrun 也是基于 torch.distributed 实现的,主要区别在于它简化了启动分布式进程的逻辑,底层仍然使用 PyTorch 的 NCCL 或 Gloo 后端来进行进程间通信。

- **NCCL**:主要用于 GPU 间的高效通信。 - **Gloo**:可用于 CPU 和 GPU 间通信,适应性广。

使用方法

通过命令行启动:

bash
torchrun --nproc_per_node=4 \ --nnodes=2 \ --node_rank=0 \ --rdzv_backend=c10d \ --rdzv_endpoint="192.168.1.1:29400" \ train.py
  • --nproc_per_node=4

    • 指定每个节点上运行的进程数量,通常等于每台服务器的 GPU 数量(比如这里是 4)。
  • --nnodes=2

    • 设置分布式训练中使用的节点总数。这里的 2 表示有两台服务器共同参与训练。
  • --node_rank=0

    • 当前节点的编号,编号从 0 开始。不同节点上会设置不同的 node_rank 值,如 01
  • --rdzv_backend=c10d

    • Rendezvous(集合点)用于节点发现和通信初始化,c10d 是一种 PyTorch 的后端协议,提供分布式训练的基础设施。
  • --rdzv_endpoint="192.168.1.1:29400"

    • 设定集合点的 IP 地址和端口号,所有节点需要通过这个集合点进行协调和通信初始化。

--rdzv_backend=c10d 这个参数指定了 PyTorch 用于节点间的集合点(Rendezvous)机制的后端:

    1. Rendezvous(集合点): 在分布式训练中,多个节点(服务器)需要相互连接并同步进行训练。Rendezvous 是用于协调这些节点的集合点,它负责让每个节点在开始训练之前找到并连接其他节点,从而形成一个分布式训练集群。
    1. c10d 后端c10d 是 PyTorch 内部的一个分布式通信后端协议,支持多进程和多节点之间的通信。它基于低层次的通信协议(如 TCP/IP)来实现节点的发现、连接和进程间的数据同步。

    • 节点发现:每个训练节点需要通过集合点与其他节点进行通信。例如,你的训练代码在两台服务器上运行,所有节点需要通过 rdzv_endpoint 这个集合点来相互发现对方。
    • 通信初始化:一旦节点通过集合点互相发现,它们会根据指定的后端(如 NCCL 或 Gloo)进行进程间通信的初始化。
    1. 为什么需要指定 rdzv_backendrdzv_backend 用于选择如何管理节点之间的连接。c10d 是 PyTorch 默认的一个集合点后端,主要用于协调各个节点在训练开始之前进行连接和通信初始化。通过这种机制,多个节点可以协同工作,开始分布式训练。

简单来说,--rdzv_backend=c10d 是在告诉 PyTorch 使用 c10d 这个后端来协调分布式训练节点的发现和连接过程。

--master_addr 和 --master_port:

这是旧版 torch.distributed 启动分布式训练时常用的参数,专门用于设置主节点的地址和端口。主节点(master node)会负责进程间的同步和通信。当使用这些参数时,训练需要明确指定哪一台机器是主节点,其他节点会连接到该主节点,借助它进行训练同步和控制。

--rdzv_backend 和 --rdzv_endpoint:

这是 torchrun 提供的更先进的分布式节点管理方式,支持更灵活和健壮的节点协调机制。它通过 Rendezvous 集合点来实现节点发现、通信初始化,不需要明确指定一个主节点。这个机制相比旧版更加灵活,尤其是在容错处理和多节点动态加入方面。

  1. --rdzv_backend:指定用于协调节点的后端,比如 c10d 是一种常见的选择。
  2. --rdzv_endpoint:指定 Rendezvous 集合点的 IP 和端口,所有节点通过这个集合点相互发现并建立通信。

交互性

  • 需要通过命令行启动,无法直接交互。

3. accelerate

特点与功能

accelerate 是由 Hugging Face 推出的库,旨在简化分布式和混合精度训练的配置与管理。与 PyTorch 的原生工具相比,accelerate 更加注重用户体验,并自动化了分布式训练的许多配置步骤。

优势

  • 自动配置:用户无需手动配置分布式环境,accelerate 会自动检测并配置设备。
  • 支持多种硬件加速:不仅支持多机多卡的 GPU 加速,还支持 TPU、FP16 混合精度等。
  • 与 Hugging Face 生态无缝集成:特别适用于 Hugging Face 的 Transformers 模型。
  • 易于调试accelerate 提供了一些工具用于方便地检查分布式设置,且其接口非常直观,易于使用。

底层架构

accelerate 封装了 PyTorch 的分布式库,并添加了额外的逻辑来简化用户的配置工作。其背后依然依赖 NCCL 或 Gloo 进行设备间通信,但它将用户的手动配置降至最低,并通过高层 API 将分布式训练任务透明化。

使用方法1

首先安装 accelerate

bash
pip install accelerate

配置并启动分布式训练:

bash
accelerate config accelerate launch train.py

在配置过程中,用户只需回答几个简单的问题(如设备数量、训练类型等),accelerate 将根据配置自动管理分布式进程和设备通信。

使用方法2

accelerate 支持使用 YAML 文件直接配置分布式训练。你可以通过创建一个 YAML 文件来定义所需的配置,从而简化配置过程。具体步骤如下:

  1. 创建 YAML 配置文件

    你可以手动创建一个配置文件,比如 accelerate_config.yaml,并写入你的配置参数。

    示例 YAML 文件:

    yaml
    compute_environment: LOCAL_MACHINE deepspeed_config: {} distributed_type: MULTI_GPU fp16: false machine_rank: 0 main_process_ip: null main_process_port: null mixed_precision: no num_machines: 1 num_processes: 2 use_cpu: false
  • compute_environment: LOCAL_MACHINE

    • 含义:指定训练的计算环境。LOCAL_MACHINE 表示在本地机器上进行训练。
    • 可选值
      • LOCAL_MACHINE: 本地机器。
      • AWS, GCP, Azure: 云端环境。
  • deepspeed_config: {}

    • 含义:配置 DeepSpeed 参数。如果没有使用 DeepSpeed,可以留空 {}
    • 可选值
      • {}: 不使用 DeepSpeed
      • 其他值为 DeepSpeed 配置文件路径。
  • distributed_type: MULTI_GPU

    • 含义:指定分布式训练的类型。
    • 可选值
      • NO: 不使用分布式训练。
      • MULTI_GPU: 使用多块 GPU 进行训练。
      • MULTI_CPU: 使用多核 CPU 进行训练。
      • TPU: 使用 TPU 进行训练。
  • fp16: false

    • 含义:是否启用混合精度训练,使用 16 位浮点数进行计算。
    • 可选值
      • true: 启用混合精度训练,提升速度和减少内存占用。
      • false: 使用默认的 32 位浮点数计算。
  • machine_rank: 0

    • 含义:指定当前机器的排名,通常在多机训练时使用。对于单机训练,该值为 0
    • 可选值
      • 整数值,表示机器的排名。
  • main_process_ip: null

    • 含义:指定主节点的 IP 地址。在多机训练中主节点负责设备间通信。
    • 可选值
      • null: 单机训练。
      • 有效的 IP 地址:多机训练时的主节点 IP。
  • main_process_port: null

    • 含义:指定主节点通信使用的端口号。
    • 可选值
      • null: 单机训练。
      • 端口号:多机训练时通信所用的端口。
  • mixed_precision: no

    • 含义:控制是否使用混合精度训练,以提高性能和减少显存占用。
    • 可选值
      • no: 不使用混合精度。
      • fp16: 使用 16 位浮点数进行混合精度训练。
      • bf16: 使用 bfloat16 混合精度(适用于某些硬件)。
  • num_machines: 1

    • 含义:指定参与训练的机器数量。
    • 可选值
      • 正整数值:例如 1 表示单机训练,多机训练时指定机器数量。
  • num_processes: 2

    • 含义:指定每台机器上的进程数,通常等于 GPU 的数量。
    • 可选值
      • 正整数值:例如 2 表示使用 2 个进程,通常对应 2 块 GPU。
  • use_cpu: false

    • 含义:是否强制使用 CPU 进行训练。
    • 可选值
      • true: 强制使用 CPU 进行训练。

      • false: 默认使用 GPU 训练(如果可用)。

  1. 运行时指定 YAML 配置

    在运行训练脚本时,你可以通过以下命令加载该 YAML 文件:

    bash
    accelerate launch --config_file accelerate_config.yaml train.py

通过这种方式,你可以跳过交互式的配置过程,直接使用预先定义好的设置来管理分布式训练。

这样可以使得配置过程更加自动化和可复用,特别是当你需要在不同的环境中进行多次训练时。

accelerate + DeepSpeed

accelerate 支持通过 deepspeed_config 参数来集成 DeepSpeed,从而利用其优化功能(如分布式训练、模型并行、梯度累积等)。如果需要使用 DeepSpeed,可以在 deepspeed_config 字段中传递 DeepSpeed 的配置参数。

deepspeed_config 的配置方法

deepspeed_config 参数通常是一个指向 JSON 文件或直接嵌入的 JSON 对象,用来配置 DeepSpeed。该 JSON 文件中会包含各种与 DeepSpeed 相关的设置,比如优化器、学习率调度器、混合精度训练等。

示例配置:

你可以将 deepspeed_config 写成一个 JSON 文件并指定路径,或者直接在 YAML 中嵌入。

  1. 创建一个 JSON 配置文件(如 ds_config.json):

    json
    { "train_batch_size": 16, "gradient_accumulation_steps": 4, "fp16": { "enabled": true, "loss_scale": 0, "initial_scale_power": 16 }, "optimizer": { "type": "AdamW", "params": { "lr": 0.00015, "betas": [0.9, 0.999], "eps": 1e-8, "weight_decay": 0.01 } }, "scheduler": { "type": "WarmupLR", "params": { "warmup_min_lr": 0, "warmup_max_lr": 0.00015, "warmup_num_steps": 1000 } } }
  2. accelerate_config.yaml 中使用 deepspeed_config

    yaml
    deepspeed_config: ds_config.json

或者,你可以将 deepspeed_config 直接写入 YAML 文件中,如下所示:

yaml
deepspeed_config: train_batch_size: 16 gradient_accumulation_steps: 4 fp16: enabled: true loss_scale: 0 initial_scale_power: 16 optimizer: type: AdamW params: lr: 0.00015 betas: [0.9, 0.999] eps: 1e-8 weight_decay: 0.01 scheduler: type: WarmupLR params: warmup_min_lr: 0 warmup_max_lr: 0.00015 warmup_num_steps: 1000
常见的 DeepSpeed 配置参数
  • train_batch_size: 设置全局批次大小(包括所有设备上的累积批次)。
  • gradient_accumulation_steps: 梯度累积步数,减少显存占用。
  • fp16: 混合精度训练的配置。
    • enabled: 是否启用混合精度。
    • loss_scale: 损失缩放。
    • initial_scale_power: 缩放的初始指数。
  • optimizer: 优化器设置。
    • type: 优化器类型,如 AdamW
    • params: 包括学习率、动量参数等。
  • scheduler: 学习率调度器。
    • type: 调度器类型,如 WarmupLR
    • params: 调度器的参数,如 warmup_min_lrwarmup_max_lr 等。

通过这种方式,DeepSpeed 可以与 accelerate 无缝集成,用于分布式和高效的模型训练。

ZeRO-3

DeepSpeed 的 ZeRO(Zero Redundancy Optimizer)技术,其中 ZeRO Stage 3(简称为 ZeRO-3)是 DeepSpeed 的一个高效分布式并行技术,它可以极大地降低显存占用,使得训练非常大的模型成为可能。ZeRO-3 通过对模型参数、优化器状态和梯度的全局分片来减少显存使用,实现了更高效的分布式训练。

配置 ZeRO-3 的步骤

DeepSpeed 的 ZeRO-3 配置通常是在 deepspeed_config 中通过启用 zero_optimization 字段来实现的。以下是一个典型的 ZeRO Stage 3 配置示例:

示例 deepspeed_config.json
json
{ "train_batch_size": 16, "gradient_accumulation_steps": 4, "fp16": { "enabled": true, "loss_scale": 0, "initial_scale_power": 16 }, "zero_optimization": { "stage": 3, "overlap_comm": true, "contiguous_gradients": true, "reduce_bucket_size": 5e8, "stage3_prefetch_bucket_size": 5e8, "stage3_param_persistence_threshold": 1e6, "stage3_max_live_parameters": 1e9, "stage3_max_reuse_distance": 1e6, "stage3_gather_fp16_weights_on_model_save": true }, "optimizer": { "type": "AdamW", "params": { "lr": 0.00015, "betas": [0.9, 0.999], "eps": 1e-8, "weight_decay": 0.01 } }, "scheduler": { "type": "WarmupLR", "params": { "warmup_min_lr": 0, "warmup_max_lr": 0.00015, "warmup_num_steps": 1000 } } }
  • zero_optimization.stage: 3: 表示启用 ZeRO Stage 3。Stage 3 分片模型参数、优化器状态和梯度,这比 Stage 1 和 2 更省内存。

  • overlap_comm: true: 启用通信与计算的重叠,以提升训练效率。

  • contiguous_gradients: true: 在内存中连续存储梯度,以减少显存碎片。

  • reduce_bucket_size: 5e8: 梯度减少的 bucket 大小。这个值越大,通信和计算的开销就越大,但显存使用更高效。

  • stage3_prefetch_bucket_size: 5e8: 预取的 bucket 大小,用于参数交换时的优化。

  • stage3_param_persistence_threshold: 1e6: 持久存储参数的阈值,超过此大小的参数会在内存中保持不被分片。

  • stage3_max_live_parameters: 同时保持在内存中的最大参数数目。

  • stage3_max_reuse_distance: 参数复用的最大距离,用于优化参数访问模式。

  • stage3_gather_fp16_weights_on_model_save: true: 在保存模型时,将 FP16 权重聚合到主节点上。

通过 ZeRO Stage 3,你可以训练比显存容量大得多的模型,并且显著降低单机多卡的内存占用。

交互性

  • 高度交互:通过命令行的 accelerate config,用户可以交互式地配置分布式训练环境。

4. DeepSpeed

特点与功能

DeepSpeed 是由微软推出的一个高性能分布式深度学习库,专注于加速大规模模型的训练,特别是在多卡、多机、多节点上表现出色。与 PyTorch 的原生分布式库相比,DeepSpeed 提供了额外的优化功能,如 ZeRO 优化器、混合精度训练等。

优势

  • ZeRO 优化器:通过优化显存使用,使得训练更大模型成为可能。
  • 深度优化:支持梯度累积、模型并行、流水线并行等高级特性。
  • 混合精度和超参数调优:内置了 FP16 训练和自动微调技术,减少显存消耗并提高训练速度。
  • 与 PyTorch 无缝集成:支持 Hugging Face Transformers 等主流模型,方便用户迁移现有代码。

底层架构

DeepSpeed 基于 PyTorch 的 torch.distributed,但引入了额外的内存优化技术(如 ZeRO 分布式优化),并在通信、数据并行以及梯度计算上进行了大量优化,旨在最大限度地提高硬件资源利用率。

使用方法

安装 DeepSpeed

bash
pip install deepspeed

使用 DeepSpeed 启动分布式训练:

bash
deepspeed --num_gpus=8 train.py --deepspeed_config ds_config.json

其中,ds_config.json 文件包含关于优化、显存管理和训练参数的配置。

DeepSpeed 支持多机多卡分布式训练。你可以通过配置 DeepSpeed 和使用合适的启动命令来进行跨多台机器的分布式训练。

多机多卡训练步骤
  1. 配置 deepspeed_config.json 文件: 多机多卡训练时,deepspeed_config.json 文件不需要做特殊修改,与单机多卡的配置文件是一样的。重要的是如何启动多机环境。

    示例配置文件(ds_config.json):

    json
    { "train_batch_size": 16, "gradient_accumulation_steps": 4, "fp16": { "enabled": true, "loss_scale": 0, "initial_scale_power": 16 }, "zero_optimization": { "stage": 3, "overlap_comm": true, "contiguous_gradients": true, "reduce_bucket_size": 5e8, "stage3_prefetch_bucket_size": 5e8, "stage3_param_persistence_threshold": 1e6 }, "optimizer": { "type": "AdamW", "params": { "lr": 0.00015, "betas": [0.9, 0.999], "eps": 1e-8, "weight_decay": 0.01 } }, "scheduler": { "type": "WarmupLR", "params": { "warmup_min_lr": 0, "warmup_max_lr": 0.00015, "warmup_num_steps": 1000 } } }
  2. 配置多机环境: 在多机训练中,需要设置机器的 IP 地址、端口等信息来协调多台机器进行训练。使用 DeepSpeed 进行多机训练时,你可以通过以下两种方式来实现:

    • 手动启动:为每台机器分配相应的 rank 和节点信息。
    • 自动化启动:使用诸如 pdsh 或者 slurm 等作业调度系统。
  3. 启动多机训练

    手动启动

    • 你可以通过在每台机器上运行以下命令来手动启动多机分布式训练:
    bash
    deepspeed --num_gpus=8 train.py --deepspeed_config ds_config.json \ --master_addr="主节点的IP" \ --master_port="主节点使用的端口" \ --num_nodes=2 \ --node_rank=0 # 对于主节点是0,对于其他节点是1、2、3等

    参数说明

    • --master_addr: 主节点的 IP 地址,它负责协调多个节点之间的通信。
    • --master_port: 主节点上开放的端口,用于节点间的通信。
    • --num_nodes: 训练时使用的机器数量。
    • --node_rank: 每台机器的 rank。主节点 rank 为 0,其他机器的 rank 分别为 1、2、3 等。

    在其他机器上运行类似命令,但将 --node_rank 更改为其他值(例如 1、2)。

    示例

    bash
    # 在主节点(rank 0)运行: deepspeed --num_gpus=8 train.py --deepspeed_config ds_config.json \ --master_addr="192.168.1.1" \ --master_port=12345 \ --num_nodes=2 \ --node_rank=0 # 在从节点(rank 1)运行: deepspeed --num_gpus=8 train.py --deepspeed_config ds_config.json \ --master_addr="192.168.1.1" \ --master_port=12345 \ --num_nodes=2 \ --node_rank=1
  4. 使用集群管理器启动: 如果你使用集群调度系统(例如 slurmpdsh),你可以通过自动化工具启动训练,而无需手动配置每台机器。

    slurm 启动示例

    bash
    srun --nodes=2 --ntasks-per-node=8 deepspeed train.py --deepspeed_config ds_config.json

DeepSpeed 支持多机多卡的分布式训练。你可以通过手动设置多机环境或使用集群管理工具(如 slurm)来启动多机训练。通过适当的配置,DeepSpeed 可以有效分配计算资源,确保大模型训练的高效性。

交互性

  • 有限的交互性:虽然 DeepSpeed 具有灵活的配置文件,但其使用主要通过配置文件和命令行参数管理。

工具对比

工具特点与优势使用场景交互性
torch.distributed.launchPyTorch 原生分布式工具,灵活强大但需手动配置标准的多机多卡训练,适用于熟悉 PyTorch 环境的用户通过命令行启动,不交互
torchrunPyTorch 1.9 引入的更简洁的分布式工具,支持 Elastic 多进程多节点、弹性训练通过命令行启动,不交互
accelerateHugging Face 工具,自动化配置,易用且与 Transformers 无缝集成快速原型开发、Hugging Face 模型训练交互式配置,简化分布式训练
DeepSpeed专注大规模模型优化,支持 ZeRO 优化器、混合精度和多种并行训练模式大规模模型训练,减少显存占用通过配置文件和命令行启动

工具的交互使用

在多机多卡的训练中,虽然每个工具都有自己的特点和优势,但它们之间可以结合使用,以最大化性能和简化配置。下面我们讨论如何将这些工具进行交互使用,以及如何选择最佳的组合来适应不同的训练场景。

torchrunDeepSpeed 的结合

torchrun 是 PyTorch 的分布式启动器,而 DeepSpeed 专注于内存优化和计算效率。这两者可以很自然地结合在一起。torchrun 负责启动分布式进程,管理跨节点、跨 GPU 的通信,而 DeepSpeed 提供内存优化(如 ZeRO 优化)和混合精度训练支持。这个组合对于需要训练超大模型的场景非常有用。

示例

bash
torchrun --nproc_per_node=8 --nnodes=2 --rdzv_backend=c10d --rdzv_endpoint="192.168.1.1:29400" train.py --deepspeed_config ds_config.json

在这个例子中,torchrun 负责管理分布式任务,而 DeepSpeed 通过配置文件 ds_config.json 提供优化方案。

accelerateDeepSpeed 的结合

accelerateDeepSpeed 的结合同样非常有用。accelerate 自动化了分布式训练环境的设置,它会检测可用的硬件资源,并根据用户的需求进行优化配置。而 DeepSpeed 进一步提供了模型优化和内存管理的技术,如梯度检查点和混合精度计算。对于快速开发 Hugging Face 的模型,并希望利用大规模分布式和优化技术的用户来说,这种组合极为理想。

示例

bash
accelerate launch --multi_gpu --mixed_precision=fp16 --deepspeed_config ds_config.json train.py

在此示例中,accelerate 管理分布式和混合精度的训练配置,而 DeepSpeed 通过 ds_config.json 文件控制模型的优化参数。

torchrunaccelerate

这两个工具可以结合使用,尤其适用于在弹性多进程环境中利用 accelerate 的自动化设置功能。例如,在一个多节点的分布式训练任务中,torchrun 负责启动和管理分布式进程,而 accelerate 会自动检测硬件设备(如 GPU)并为训练配置合适的参数。这个组合特别适合需要容错能力或节点动态增减的场景。

示例

bash
torchrun --nproc_per_node=4 --nnodes=3 --rdzv_backend=c10d --rdzv_endpoint="192.168.1.1:29400" accelerate launch train.py

在这个示例中,torchrun 提供分布式训练的弹性支持,而 accelerate 简化了设备检测和训练配置的过程。


工具选择指南

根据不同的训练需求,选择合适的工具组合非常关键:

  1. 纯 PyTorch 环境,多机多卡标准训练

    • 推荐使用 torch.distributed.launchtorchrun,特别是对于熟悉 PyTorch 生态的用户。
    • 当训练过程需要动态节点管理或容错时,选择 torchrun 是更好的选择。
  2. 需要简化配置、快速开始多 GPU 或多节点训练

    • 选择 accelerate 是最便捷的方式,尤其适合快速迭代模型的原型开发者或使用 Hugging Face 生态的用户。
    • 配合 DeepSpeed 可以在此基础上进一步优化大模型的训练效率。
  3. 大规模模型优化和显存节省

    • 对于需要训练超大规模模型(如 GPT-3 类)的用户,DeepSpeed 是首选。其 ZeRO 优化器能够显著降低显存开销,使得在有限硬件资源下进行大模型训练成为可能。
    • 结合 torchrunaccelerate,可以进一步简化进程管理和训练配置。

分布式训练的最佳实践

在使用这些工具进行分布式训练时,有一些通用的最佳实践,能够帮助用户更高效地管理和优化训练过程。

  1. 显存管理与模型并行: 对于大规模模型,显存是训练中的关键瓶颈。使用 DeepSpeed 的 ZeRO 优化器或梯度检查点功能,可以有效减少每张 GPU 的显存使用量。此外,模型并行(如张量并行、流水线并行)也是常见的显存优化技术。

  2. 混合精度训练: 无论是 torchrunaccelerate 还是 DeepSpeed,都支持混合精度训练(FP16)。通过混合精度,用户可以在不牺牲太多模型精度的情况下加速训练,并降低显存消耗。对于使用 NVIDIA GPU 的用户,建议启用 AMP(Automatic Mixed Precision),这是由 PyTorch 提供的官方混合精度支持。

  3. 网络带宽与通信优化: 在多机多卡训练中,节点间的网络带宽往往成为瓶颈。使用 NCCL 后端时,尽量选择高带宽的网络连接(如 InfiniBand)。此外,DeepSpeed 和 PyTorch 都支持梯度累积和通信延迟技术,能够有效减少网络通信对训练速度的影响。

  4. 弹性训练: 弹性训练(Elastic Training)是现代分布式训练的趋势,特别是在云端训练中,节点的动态增减是常见的场景。使用 torchrunaccelerate,用户可以配置容错机制,使得某些节点在训练中断时,其他节点可以继续训练任务。

  5. 自动超参数调优: 大多数分布式训练任务都涉及大量超参数调整。使用 accelerateDeepSpeed,可以通过自动化工具(如 OptunaRay Tune)进行超参数调优,从而减少手动调试时间,提高模型的最终性能。


总结

在多机多卡的深度学习训练环境中,python -m torch.distributed.launchtorchrunaccelerateDeepSpeed 都是强大的分布式训练工具。每个工具都有自己的特点和优势,适合不同的使用场景:

  • torch.distributed.launchtorchrun 是 PyTorch 提供的原生分布式训练工具,适合需要手动配置和高度定制化的用户。
  • accelerate 则更侧重于简化配置、加快开发流程,特别是对于 Hugging Face 的 Transformers 模型用户。
  • DeepSpeed 提供了卓越的大规模模型优化,特别适合显存敏感的超大规模模型训练。

通过灵活组合这些工具,用户可以实现高效、低成本的分布式训练,并最大化硬件资源的利用率。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!