基于多台开发机分布式训练
网络硬件与通信库
基于多台英博云开发机,可以实现分布式训练,若您采用的是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_test,可以任选一台开发机,将其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
注意:
- 关于算力网络的更多信息,参考这里