任务式建模支持提交多机多卡分布式训练任务,TI-ONE 平台支持多种分布式训练模式,包含 DDP、Ray、MPI、PS-Worker 等,本文档将阐述不同训练方式在 TI-ONE 平台中的使用方法。此外,大规模分布式训练任务需要使用 RDMA 技术来获得高吞吐、低延迟的网络通信,从而提升训练效率。本文最后也将介绍如何在 TI-ONE 平台上基于 RDMA 的高性能 GPU 实例进行分布式训练。
一、支持的分布式训练模式及使用说明
TIONE 任务式建模支持多种分布式训练模式,包含 DDP、Ray、MPI、PS-Worker 等,以下是平台支持的分布式训练模式及其使用场景概述:
分布式训练模式 | 模式介绍 |
DDP | PyTorch DistributedDataParallel(DDP)是一种数据并行的分布式训练方法。通过 DDP 创建多个进程进行模型训练,通过 ring-all-reduce 的方法做进程通讯,完成梯度的交换及参数更新。 |
MPI | MPI 是一种基于信息传递的并行编程技术。平台支持用户发起 MPI 的分布式训练任务,同时也支持常见的 Horovod、DeepSpeed 等基于 MPI 的训练框架。 |
Ray | Ray 是一个开源的分布式计算框架,能够简化分布式机器学习的开发和部署。Ray 提供了一套 API 和基础设施,使得开发人员可以轻松地将单机训练代码扩展到分布式环境,支持数据并行和模型并行等多种并行策略。Ray 在大模型领域也常用作加速强化学习训练过程的分布式框架。 |
PS-Worker | PS(ParameterServer)参数服务器训练是一种常见的数据并行方法,用于在多台机器上扩展模型训练。训练集群由 Worker 和 ParameterServer(ps) 组成。参数保存在 ps 上,在每一轮训练中,ps 将参数分发给 worker,worker 完成计算后将梯度回传给 ps 进行更新。 |
DDP 模式使用说明
PyTorch DistributedDataParallel(DDP)训练模式支持在 PyTorch 中进行数据并行训练。数据并行模式可以跨多个进程同时处理多个数据批次,每个进程的输入数据批次不重叠,每个进程计算梯度并使用 ring-all-reduce 算法完成与其他进程的同步。
使用方式
1. 在 “任务式建模” 界面创建训练任务时,选择训练模式为 DDP,并配置单节点资源和节点个数。其中启动命令会在每个节点上被执行。
2. DDP 训练模式包含两种角色 Master 和 Worker。其中编号为0的是 Master(对应环境变量中 RANK=0),承担保存模型的任务。
3. TI 平台会根据任务配置创建对应的实例,并注入相关的环境变量,如任务中包含的实例组信息,以及当前实例的角色。Worker 会等待 Master 正常启动,网络通畅。以下是任务式建模启动时默认注入的环境变量列表:
内置环境变量
变量名 | 变量描述 | 示例 |
NODE_LIST | 训练任务公共环境变量:任务节点的列表和节点的 GPU 卡数信息 | NODE_LIST=timaker-xxxyyy-launcher.training-job.svc.cluster.local:1,timaker-xxxyyy-worker-0.training-job.svc.cluster.local:1 |
INDEX | 训练任务公共环境变量:当前节点信息在 NODE_LIST 的索引,从0开始 | INDEX=1 |
MASTER_ADDR | DDP 训练任务的 master 节点 IP | MASTER_ADDR=10.35.110.11 |
MASTER_PORT | DDP 训练任务的 master 节点端口 | MASTER_PORT=23456 |
WORLD_SIZE | DDP 训练任务的节点数 | WORLD_SIZE=2 |
RANK | DDP 训练任务的当前节点 | RANK=1 |
GPU_NUM | 任务包含的 GPU 卡总数 | GPU_NUM=2 |
GPU_NUM_PER_NODE | 单个节点的 GPU 卡数 | GPU_NUM_PER_NODE=1 |
4. 训练过程中任意实例退出码非0则训练任务失败。所有实例成功则训练任务成功。
示例启动方式
启动 DDP 分布式训练的命令示例如下:
python -m torch.distributed.launch --nproc_per_node $GPU_NUM_PER_NODE --nnodes $WORLD_SIZE --node_rank $RANK --master_addr $MASTER_ADDR --master_port $MASTER_PORT
DDP 分布式训练参数与平台环境变量对应关系如下表所示:
变量名 | 变量描述 |
nproc_per_node | 单个实例(机器)上运行的进程数,使用 GPU 时通常为每台机器上的 GPU 卡数,对应环境变量 GPU_NUM_PER_NODE 的值。 |
nnodes | 对应环境变量 WORLD_SIZE 的值。 |
node_rank | 对应环境变量 RANK 的值。 |
master_addr | 对应环境变量 MASTER_ADDR 的值。 |
master_port | 对应环境变量 MASTER_PORT 的值。 |
对于启动命令中涉及的内置环境变量,平台会在启动任务式建模任务时注入。而在 Notebook 或者本地调试代码时,需要开发人员先为对应环境变量赋值。为了方便调试使用,可以为对应环境变量设置默认值,示例如下:
MASTER_ADDR=${MASTER_ADDR:-localhost} MASTER_PORT=${MASTER_PORT:-23456} NNODES=${WORLD_SIZE:-1} NODE_RANK=${RANK:-0} GPU_PER_NODE=${GPU_NUM_PER_NODE:-$(nvidia-smi -L | wc -l)} python -m torch.distributed.launch --nproc_per_node $GPU_PER_NODE --nnodes $NNODES --node_rank $NODE_RANK --master_addr $MASTER_ADDR --master_port $MASTER_PORT
MPI/Horovod 模式使用说明
MPI 是一种用于分布式并行训练的消息传递标准。平台支持用户发起 MPI 模式的分布式训练任务,并也支持常见的基于 MPI 通信的训练框架如 Horovod。而 Horovod 训练模式则是更原生适配了以 Horovod 框架进行训练的任务。本文以上述两种训练模式为例,介绍如何在机器学习平台上发起分布式训练任务。
使用方式
1. 在 “任务式建模” 界面创建训练任务时,选择训练模式为 MPI/Horovod,并配置单节点资源和节点个数。
2. MPI 训练模式和 Horovod 模式均包含 Launcher 和 Worker 两种角色,但两种角色均可执行训练任务,当任务仅配置一个实例时默认创建 Launcher 实例。
3. MPI 模式启动命令会在每个实例上执行。而 Horovod 模式启动命令仅会在 Launcher 实例上执行,Worker 实例的命令被配置为 sleep infinity 等待 Launcher 的命令。以下是任务式建模启动时默认注入的环境变量列表:
内置环境变量
变量名 | 变量描述 | 示例 |
OMPI_MCA_orte_default_hostfile | MPI/Horovod 训练任务的节点信息文件 | OMPI_MCA_orte_default_hostfile=/etc/mpi/hostfile |
GPU_NUM | 任务包含的 GPU 卡总数 | GPU_NUM=2 |
GPU_NUM_PER_NODE | 单个节点的 GPU 卡数 | GPU_NUM_PER_NODE=1 |
NODE_IP_SLOT_LIST | 任务包含的节点 IP 和对应卡数信息(仅支持用于配置启动命令) | NODE_IP_SLOT_LIST=9.0.255.56:1,9.0.255.118:1 |
4. TI 平台会根据任务配置创建对应的实例组,并注入相关环境变量,给出任务中包含的实例组信息,以及当前实例的角色。
5. 训练过程中任意实例退出码非0则训练任务失败。所有实例成功则训练任务成功。
示例启动方式
其中 /etc/mpi/hostfile 的内容示例如下:
train-960258573108964736-7an39bddmfpc-launcher slots=1 train-960258573108964736-7an39bddmfpc-worker-0 slots=1
内容分为两列,第一列是实例的域名,第二列是实例上的进程个数。
启动 MPI/Horovod 分布式训练的命令示例如下:
# MPI方式启动mpirun --allow-run-as-root -np $GPU_NUM -H $NODE_IP_SLOT_LIST python3 train.py --data-dir /opt/ml/input/data# horovod方式启动horovodrun -np $GPU_NUM -H $NODE_IP_SLOT_LIST --network-interface eth0 python3 train.py --data-dir /opt/ml/input/data
此外, DeepSpeed 框架支持使用 OpenMPI 格式的 hostfiles 来配置多节点计算资源,使用 MPI 启动 DeepSpeed 分布式训练操作实践请查看 使用任务式建模运行 DeepSpeed 分布式训练指引。
PS-worker 模式使用说明
PS(ParameterServer)参数服务器训练是一种常见的数据并行方法,用于在多台机器上扩展模型训练。训练集群由 Worker 和 ParameterServer(ps) 组成。参数保存在 ps 上,在每一轮训练中,ps 将参数分发给 worker,worker 完成计算后将梯度回传给 ps 进行更新。
使用方式
1. 在 “任务式建模” 界面创建训练任务时,选择训练模式为 PS-Worker,并配置单节点资源和节点个数。
2. 平台提供的 PS-Worker 训练模式包含两种角色:ps 和 worker。ps 保存和更新参数,实例数量应>=1,worker 负责执行训练,实例数量应>=1。
3. TI 平台会根据任务配置创建对应的实例,并注入对应的环境变量 TF_CONFIG,给出了任务中包含的实例组信息,以及当前实例的角色。实例通过读取 TF_CONFIG 得到任务中 ps/worker 的数量和地址,并通过 task 中的 type 得知当前实例所属的角色和编号。
环境变量
TF_CONFIG
{ "cluster": { "ps": [ "train-960252492096760832-7an13ppfli80-ps-0.train-100031385875.svc:2222", "train-960252492096760832-7an13ppfli80-ps-1.train-100031385875.svc:2222" ], "worker": [ "train-960252492096760832-7an13ppfli80-worker-0.train-100031385875.svc:2222", "train-960252492096760832-7an13ppfli80-worker-1.train-100031385875.svc:2222" ] }, "task": { "type": "ps", "index": 0 }, "environment": "cloud" }
4. 训练过程中任意实例退出码非0则训练任务失败。所有实例成功则训练任务成功。
Ray 模式使用说明
Ray 是一个开源的分布式计算框架,能够简化分布式机器学习的开发和部署。Ray 提供了一套 API 和基础设施,使得开发人员可以轻松地将单机训练代码扩展到分布式环境,支持数据并行和模型并行等多种并行策略。
使用方式
1. 在"任务式建模"界面创建训练任务时,选择训练模式为 Ray,并配置 Head 节点资源和各组 Worker 节点资源和个数,Worker 最多可配置5组。
2. Ray 训练模式包含两种角色:Head 和 Worker。其中编号为0的是 Head 节点(对应环境变量中 RANK=0),负责协调整个集群的计算资源和任务调度,Worker 节点则执行具体的训练任务。
3. TI 平台会根据任务配置创建对应的实例,并注入相关的环境变量,以下是任务式建模启动时默认注入的环境变量列表:
变量名 | 变量描述 | 示例 |
HEAD_ADDR | Ray 集群的 Head 节点地址 | HEAD_ADDR=train-1282671078021627392-9qu5j2n90b9c-head-0 |
HEAD_PORT | Ray 集群的 Head 节点端口 | HEAD_PORT=6379 |
RANK | 当前节点在集群中的序号,RANK0 为 HEAD 节点 | RANK=0 |
示例启动方式
您只需要在您的代码中,使用 ray.init() 默认初始化即可,并把您的脚本执行命令配置到启动命令,我们会默认在 Head 节点上提交您的任务到集群中,您无需指定 Head 节点的地址。
以一个简单的计数任务为例,将如下代码保存为
job.py。import rayray.init()# 定义 Actor 类@ray.remoteclass Counter:def __init__(self):self.value = 0def increment(self):self.value += 1return self.value# 创建 Actor 实例counter = Counter.remote()# 并发调用 Actor 方法futures = [counter.increment.remote() for _ in range(10)]results = ray.get(futures) # [1, 2, 3, ..., 10]print("计数器结果:", results)
job.py 作为训练任务,放到您的 CFS 或 GooseFSx 指定目录,并在任务式建模中选择挂载到
/opt/ml/code 目录,然后指定启动命令为:cd /opt/ml/code; python job.py
在训练任务中,可以通过 INDEX 指定节点,以指定在 INDEX = 1 的节点执行如下函数为例:
@ray.remote(resources={"Rank:1": 0.001})def f(a, b, c):return a + b + c
注意:
1. 暂时不支持 Ray dashboard 的查看。
2. Ray 的设计是基于整数资源调度的。例如,一个任务声明需要 1 个 CPU,Ray 会确保它独占一个完整的物理核心,避免资源竞争。 因此建议在配置 Ray 资源组的 CPU 资源时避免使用小数核数,例如设置0.7核,Ray 会将您的设置向下取整,例如 0.7 会被截断为 0,这可能导致程序行为不符合预期(例如任务无法运行)。
3. 由于 TIONE 平台支持 GPU 碎片调度,例如0.2卡资源。在 Ray 集群内部,Worker 会把0.2卡当成一块完整的 GPU 来使用,可以通过 nums_gpu=1 来设置。
二、发起 RDMA 网络加速训练
RDMA 是 kernel by pass 的一种通信技术,在多机通信场景可显著提升通信带宽。本文将介绍如何在 TIONE 平台任务式建模使用 RDMA 网络。
使用前提
1. 资源组中至少包含2台支持 RDMA 的高性能 GPU 节点。
2. 提交的分布式任务配置为大于等于2个节点,且每个节点配置为8卡整机 GPU 资源,平台会默认为该资源配置 RDMA 资源。
3. 平台 llm 内置镜像默认支持常见的 HCC 高性能 GPU 机型,自定义镜像需要安装用户态 RDMA 驱动,安装文档参考 容器安装用户态 RDMA 驱动。
如何确认 RDMA 是否生效
在平台上运行的多机任务,如果开启了 RDMA,则会有以下日志:
[0] NCCL INFO Channel 00/0 : 8[0] -> 0[0] [receive] via NET/IBext/0/GDRDMA
平台内置的环境变量
针对 HCC 机型多机训练场景会开启 RDMA,并且会内置以下 NCCL 环境变量,用户使用 TI 平台的时候,无需显式设置。
NCCL_IB_GID_INDEX=3NCCL_IB_SL=3NCCL_CHECK_DISABLE=1NCCL_P2P_DISABLE=0NCCL_IB_DISABLE=0NCCL_LL_THRESHOLD=16384NCCL_IB_CUDA_SUPPORT=1NCCL_IB_HCA=mlx5_bondNCCL_NET_GDR_LEVEL=2NCCL_IB_QPS_PER_CONNECTION=4NCCL_IB_TC=160NCCL_PXN_DISABLE=1NCCL_IB_TIMEOUT=24NCCL_DEBUG=INFONCCL_SOCKET_IFNAME=eth0GLOO_SOCKET_IFNAME=eth0TCCL_TOPO_AFFINITY=4