任务式建模支持提交多机多卡分布式训练任务,TI-ONE 平台支持多种分布式训练模式,包含 DDP、Ray、MPI、PS-Worker 等,本文档将阐述不同训练方式在 TI-ONE 平台中的使用方法。此外,大规模分布式训练任务需要使用 RDMA 技术来获得高吞吐、低延迟的网络通信,从而提升训练效率。本文最后也将介绍如何在 TI-ONE 平台上基于 RDMA 的高性能 GPU 实例进行分布式训练。
一、支持的分布式训练模式及使用说明
TIONE 任务式建模支持多种分布式训练模式,包含 DDP、Ray、MPI、PS-Worker 等,以下是平台支持的分布式训练模式及其使用场景概述:
| <strong>分布式训练模式</strong> | <strong>模式介绍</strong> |
| 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 算法完成与其他进程的同步。
使用方式
在 “任务式建模” 界面创建训练任务时,选择训练模式为 DDP,并配置单节点资源和节点个数。其中启动命令会在每个节点上被执行。
DDP 训练模式包含两种角色 Master 和 Worker。其中编号为0的是 Master(对应环境变量中 RANK=0),承担保存模型的任务。
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 训练过程中任意实例退出码非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 的值。 |
更多 DDP 训练参数请参考官网文档 TORCHRUN。
对于启动命令中涉及的内置环境变量,平台会在启动任务式建模任务时注入。而在 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 框架进行训练的任务。本文以上述两种训练模式为例,介绍如何在机器学习平台上发起分布式训练任务。
使用方式
- 在 “任务式建模” 界面创建训练任务时,选择训练模式为 MPI/Horovod,并配置单节点资源和节点个数。
- MPI 训练模式和 Horovod 模式均包含 Launcher 和 Worker 两种角色,但两种角色均可执行训练任务,当任务仅配置一个实例时默认创建 Launcher 实例。
- 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 |
- TI 平台会根据任务配置创建对应的实例组,并注入相关环境变量,给出任务中包含的实例组信息,以及当前实例的角色。
- 训练过程中任意实例退出码非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 进行更新。
使用方式
在 “任务式建模” 界面创建训练任务时,选择训练模式为 PS-Worker,并配置单节点资源和节点个数。
平台提供的 PS-Worker 训练模式包含两种角色:ps 和 worker。ps 保存和更新参数,实例数量应>=1,worker 负责执行训练,实例数量应>=1。
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" }训练过程中任意实例退出码非0则训练任务失败。所有实例成功则训练任务成功。
Ray 模式使用说明
Ray 是一个开源的分布式计算框架,能够简化分布式机器学习的开发和部署。Ray 提供了一套 API 和基础设施,使得开发人员可以轻松地将单机训练代码扩展到分布式环境,支持数据并行和模型并行等多种并行策略。
使用方式
- 在"任务式建模"界面创建训练任务时,选择训练模式为 Ray,并配置 Head 节点资源和各组 Worker 节点资源和个数,Worker 最多可配置5组。
- Ray 训练模式包含两种角色:Head 和 Worker。其中编号为0的是 Head 节点(对应环境变量中 RANK=0),负责协调整个集群的计算资源和任务调度,Worker 节点则执行具体的训练任务。
- 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 ray
ray.init()
# 定义 Actor 类
@ray.remote
class Counter:
def __init__(self):
self.value = 0
def increment(self):
self.value += 1
return 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 指定目录,并在任务式建模中选择挂载到 /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
注意:
- 暂时不支持 Ray tensorboard 的查看。
- Ray 的设计是基于整数资源调度的。例如,一个任务声明需要 1 个 CPU,Ray 会确保它独占一个完整的物理核心,避免资源竞争。 因此建议在配置 Ray 资源组的 CPU 资源时避免使用小数核数,例如设置0.7核,Ray 会将您的设置向下取整,例如 0.7 会被截断为 0,这可能导致程序行为不符合预期(例如任务无法运行)。
- 由于 TIONE 平台支持 GPU 碎片调度,例如0.2卡资源。在 Ray 集群内部,Worker 会把0.2卡当成一块完整的GPU来使用,可以通过 nums_gpu=1 来设置。
二、发起 RDMA 网络加速训练
RDMA 是 kernel by pass 的一种通信技术,在多机通信场景可显著提升通信带宽。本文将介绍如何在 TIONE 平台任务式建模使用 RDMA 网络。
使用前提
- 资源组中至少包含 2 台支持 RDMA 的高性能 GPU 节点。
- 提交的分布式任务配置为大于等于2个节点,且每个节点配置为8卡整机 GPU 资源,平台会默认为该资源配置 RDMA 资源。
- 平台 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=3
NCCL_IB_SL=3
NCCL_CHECK_DISABLE=1
NCCL_P2P_DISABLE=0
NCCL_IB_DISABLE=0
NCCL_LL_THRESHOLD=16384
NCCL_IB_CUDA_SUPPORT=1
NCCL_IB_HCA=mlx5_bond
NCCL_NET_GDR_LEVEL=2
NCCL_IB_QPS_PER_CONNECTION=4
NCCL_IB_TC=160
NCCL_PXN_DISABLE=1
NCCL_IB_TIMEOUT=24
NCCL_DEBUG=INFO
NCCL_SOCKET_IFNAME=eth0
GLOO_SOCKET_IFNAME=eth0
TCCL_TOPO_AFFINITY=4
NCCL 支持的环境变量参考文档 Environment Variables。