基于多台开发机分布式训练

网络硬件与通信库

基于多台英博云开发机,可以实现分布式训练,若您采用的是A800/H800开发机,便能基于InfiniBand/RoCE网络进行多机训练。

基于 PyTorch 框架编写分布式代码,通常直接采用 NCCL 作为分布式训练的通信框架。

NCCL的作用

NCCL 全称:NVIDIA Collective Communication Library,是英伟达开发的针对GPU多机通信场景的通信库,具体的作用如下:

  • 管理 GPU 之间的通信(all-reduce、broadcast、scatter-gather 等)。
  • 充分利用高速互联(NVLink、InfiniBand、RDMA)。
  • 自动拓扑优化,提高带宽利用率。

PyTorch多机训练基础

基于PyTorch进行多机训练时,典型进程结构是每个 GPU 一个进程的并行编程模型,通常通过 torch.distributed 包来实现。

核心概念:进程组 (Process Group)

进程组是所有参与分布式训练的进程的集合,它们之间通过一个后端(如 NCCL, Gloo)进行通信。关键概念包括:

  • world_size: 进程组中的总进程数(即总 GPU 数)。
  • rank: 进程组中每个进程的唯一标识符,从 0 到 world_size-1。
  • local_rank: 在一个节点(机器)内部,每个进程的唯一标识符。例如,一台有 8 张 GPU 的机器,其 local_rank 就是从 0 到 7。
典型进程结构

在多机训练场景下,进程结构遵循 主从模式 (Master-Worker)

  • Master 进程 (Rank 0):通常运行在主节点 (Master Node) 的某一张 GPU(通常是 GPU 0)上,其 rank 为 0。负责初始化分布式训练环境。所有其他进程(Worker)都需要连接到 Master 进程来获取初始配置信息,如所有进程的地址、端口、world_size 等,并同步初始状态。在启动命令中,Master 进程的地址 (--master-addr) 和端口 (--master-port) 需要被明确指定,以便所有 Worker 进程都能找到它。
  • Worker 进程 (Rank 1, 2, ... N):运行在所有节点(包括主节点和其他计算节点)的所有 GPU 上。在启动时,向 Master 进程 (--master-addr:master-port) 注册自己,并获取全局的 rank 和 world_size 信息。

2机16卡运行 PyTorch NCCL Test 示例

以下通过一个具体示例,展示在2台A800开发机内,执行16卡 NCCL 通信测试的效果。

Step 1:准备开发机

准备2台 A800 开发机,我们分别命名为 node0、node1,每台均采用A800 8卡,并挂载256MB共享存储到/data目录。

关于开发机创建,具体参考这里

Step 2:准备代码

示例代码位于英博云的github仓库:https://github.com/ebtech-ebcloud/examples/tree/main/nccl_testopen in new window,可以任选一台开发机,将其clone到/data目录中。

cd /data
git clone https://github.com/ebtech-ebcloud/examples.git   ## 下载代码
cd examples/nccl_test
Step 3:配置master_addr

master_addr 需要配置为 node0 开发机的 eth0 网卡,首先查看其 ip 地址,登录 node0 开发机执行如下命令:

apt-get update

apt-get install net-tools

ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1480
        inet 10.233.91.124  netmask 255.255.255.255  broadcast 0.0.0.0
        ether 0e:f1:22:f4:64:d3  txqueuelen 1000  (Ethernet)
        RX packets 18264  bytes 25182964 (25.1 MB)
        RX errors 0  dropped 10  overruns 0  frame 0
        TX packets 12756  bytes 6910976 (6.9 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

修改文件 run_node0.sh 和 run_node1.sh,将 MASTER_ADDR 均修改为上面获取的地址,示例如下:

MASTER_ADDR="10.233.91.124"
Step 4:执行双机通信测试

在 node0 执行:

cd /data/examples/nccl_test

bash run_node0.sh

在 node1 执行:

cd /data/examples/nccl_test

bash run_node1.sh

若是运行成功,会有nccl速度相关打印。

关键配置与代码解析

PyTorch初始分布式配置

以下初始化分布式配置的pytorch代码,这里做了2件事情:

  • 将分布式关键配置信息,记入环境变量。
  • 执行dist.init_process_group初始化分布式配置。参数:init_method='env://'表示从环境变量中读取配置信息。
def setup(rank, world_size, master_addr, master_port):
    """初始化进程组"""
    os.environ['MASTER_ADDR'] = master_addr
    os.environ['MASTER_PORT'] = master_port
    os.environ['WORLD_SIZE'] = str(world_size)
    os.environ['RANK'] = str(rank)

    # 初始化进程组
    dist.init_process_group(
        backend='nccl',  # 使用NCCL后端
        init_method='env://',
        world_size=world_size,
        rank=rank
    )
    torch.cuda.set_device(rank % torch.cuda.device_count())
NCCL Bootstrap 网络配置

Bootstrap 网络,用于在 NCCL 在建立 topo 阶段使用,这里我们使用每个开发机的eth0网卡,具体对应配置:

export NCCL_SOCKET_IFNAME=eth0 
NCCL 数据平面网络配置

数据平面网络,用于真正的通信过程,这里我们采用RDMA网卡,具体配置如下:

export NCCL_IB_HCA=mlx5_100,mlx5_101,mlx5_102,mlx5_103,mlx5_104,mlx5_105,mlx5_106,mlx5_107

注意:

  • 关于算力网络的更多信息,参考这里