使用Arena提交eRDMA加速的PyTorch分布式训练作业

在多节点 GPU 训练中网络通信延迟拖累整体性能时,为缩短模型训练周期,可利用 Arena 提交 PyTorch 分布式作业并配置 eRDMA 网络加速,实现低延迟、高吞吐的节点间通信,提升训练效率和集群利用率。

适用范围

  • 集群类型:仅支持ACK托管集群

  • 支持弹性RDMA(eRDMA)实例规格:

    • ebmgn7ex、ebmgn7ix

    • gn8is、ebmgn8is、gn8v、ebmgn8v

步骤一:安装ACK eRDMA Controller组件

您可以参见如下流程安装ACK eRDMA Controller组件。

说明
  • 如果您的集群网络插件为Terway,还需要配置Terway的网卡白名单,避免Terway组件修改eRDMA的网卡。配置方式,请参见为弹性网卡(ENI)配置白名单

  • 当节点存在多张网卡时,ACK eRDMA Controller 为附加的eRDMA网卡配置路由时,采用比同网段网卡路由更低的优先级,默认采用200的路由优先级,如果您在安装ACK eRDMA Controller后需要手动配置网卡,注意避免路由冲突。

  1. 集群列表页面,单击目标集群名称,然后在左侧导航栏,单击组件管理

  2. 组件管理页面,单击网络页签,定位ACK eRDMA Controller组件,按照页面提示配置组件并完成安装

    配置项

    说明

    preferDriver 驱动类型

    选择集群节点上使用的eRDMA驱动类型。可选值:

    • default:默认驱动模式。

    • compat:兼容RoCE驱动模式。

    • ofed:基于ofed的驱动模式,适用于GPU机型。

    关于驱动类型的详细说明,请参见启用eRDMA

    是否为Pod分配节点全部eRDMA设备

    可选值:

    • True(勾选):为Pod分配节点上所有的eRDMA设备。

    • False(不勾选):Pod根据NUMA拓扑分配一个eRDMA设备。节点需要开启CPU Static Policy才能保证Pod和设备的固定NUMA分配。关于如何配置CPU Policy,请参见创建和管理节点池

    安装完成后,您可以在左侧导航栏,选择工作负载 >容器组,然后选择命名空间为ack-erdma-controller,查看Pod运行状态,确认组件运行正常。

步骤二:节点启用eRDMA并验证

节点启用eRDMA,且确认节点上的 GPU 和 eRDMA 资源已正确识别并可被调度。
  1. GPU实例上启用eRDMA

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 容器组在创建的容器所在行,单击操作列的终端。登录到支持 eRDMA 的节点,执行以下命令查看 eRDMA 设备信息。

    预期输出中显示 erdma_0 设备且端口状态为 PORT_ACTIVE,表示 eRDMA 设备已正常启用。

    ibv_devinfo
  3. 查看节点的可分配资源。

    kubectl get node <节点名称> -o jsonpath='{.status.allocatable}'

    预期输出:

    {"aliyun/erdma":"200","cpu":"15890m","ephemeral-storage":"243149919035","hugepages-1Gi":"0","hugepages-2Mi":"0","memory":"128290128Ki","nvidia.com/gpu":"1","pods":"64"}
    • "nvidia.com/gpu":"1":表示可用的GPU数量为1。

    • "aliyun/erdma":"200":表示支持最多 200 个 Pod 使用 eRDMA。

步骤三:通过 Arena 提交训练作业

使用 Arena 提交 PyTorch 分布式训练作业,并申请 eRDMA 资源来加速节点间通信。
  1. 安装云原生AI套件的Arena组件

  2. 配置Arena客户端并提交训练作业。更多参数,请参见作业核心参数说明。

    本文使用已构建好的镜像 kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/pytorch:mnist-example 进行演示。该镜像仅用于快速体验,生产环境请参考如何构建生产环境支持 eRDMA 的容器镜像?
    arena submit pytorch \
        --name=pytorch-mnist \
        --namespace=default \
        --workers=2 \
        --gpus=1 \
        --device=aliyun/erdma=1 \
        --nproc-per-node=1 \
        --env NCCL_NET_GDR_LEVEL=1 \
        --env NCCL_P2P_LEVEL=5 \
        --env NCCL_DEBUG=INFO \
        --env NCCL_SOCKET_IFNAME=eth0 \
        --env NCCL_ALGO=Ring \
        --clean-task-policy=None \
        --working-dir=/root \
        --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/pytorch:mnist-example \
        --image-pull-policy=Always \
        --tensorboard \
        --logdir=/workspace/logs \
        "torchrun /workspace/arena/examples/pytorch/mnist/main.py \
            --epochs 10000 \
            --backend nccl \
            --data /workspace \
            --dir /workspace/logs"

步骤四:验证训练作业运行状态

确认训练作业已成功启动,并验证 eRDMA 网络已生效。
  1. 获取集群KubeConfig并通过kubectl工具连接集群

  2. 查看Master Pod的日志,训练日志显示 Train Epoch 信息,说明训练作业正常运行。

    kubectl logs pytorch-mnist-master-0 | head -n 50
  3. 验证 eRDMA 是否生效。在上述Master Pod的日志中查找关键信息 NET/IB : Using [0]erdma_0:1/RoCE,如果出现此行,表示:

    • NCCL 已成功识别 eRDMA 网卡(erdma_0)。

    • 使用 RoCE(RDMA over Converged Ethernet)协议进行通信。

    • 分布式训练的节点间通信已通过 eRDMA 加速。

步骤五:监控 eRDMA 网卡流量

实时监控eRDMA网卡的网络流量,验证数据传输情况。
  1. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 容器组在创建的容器所在行,单击操作列的终端。登录到训练节点,执行以下命令监控 eRDMA 网卡流量。

    eadm stat -d erdma_0 -l

    预期输出为rx(下载): 914.89 MiB/s 150423 p/s; tx(上传):914.66 MiB/s 147128 p/s,训练过程中看到持续上传下载的双向流量,表示节点间正在进行梯度同步等通信操作。

  2. 通过控制台使用AI Profiling分析训练性能。

    ACK 集群提供了 AI Profiling 功能,可以从 Torch、Python 和 CUDA Kernel 多个层面分析训练性能。通过 Profiling 工具深入分析训练作业的性能瓶颈,包括计算、通信和内存使用情况。

清理资源

训练作业完成后,执行以下命令删除作业:

此操作将删除作业相关的所有 Pod 和资源,但不会删除 TensorBoard 日志等持久化数据。
arena delete pytorch-mnist -n default

预期输出:

INFO[0001] The training job pytorch-mnist has been deleted successfully

常见问题

为什么日志中没有显示 NET/IB : Using erdma_0

可能的原因包括:

  • 未在提交命令中添加 --device=aliyun/erdma=1 参数。

  • 节点不支持 eRDMA 或 eRDMA Controller 组件未正确安装。

  • 容器镜像中缺少 RDMA 用户态库(libibverbs、librdmacm 等)。

解决方法:

  1. 执行 kubectl get node <节点名> -o jsonpath='{.status.allocatable}' 确认节点是否有 aliyun/erdma 资源。

  2. 登录节点执行 ibv_devinfo 检查 eRDMA 设备是否正常。

  3. 检查容器镜像是否包含必要的 RDMA 库。

训练过程中出现 NCCL timeout 错误怎么办?

NCCL timeout 通常由网络不稳定或配置不当引起。建议:

  1. 增加超时时间:设置 --env NCCL_IB_TIMEOUT=23(默认为 22)。

  2. 增加重试次数:设置 --env NCCL_IB_RETRY_CNT=10

  3. 检查节点间的网络连通性和 eRDMA 设备状态。

如何判断 eRDMA 是否真正提升了训练性能?

可以通过以下方式对比:

  1. 分别提交使用 eRDMA 和不使用 eRDMA 的训练作业(通过是否添加 --device=aliyun/erdma=1 区分)。

  2. 对比相同训练步数下的完成时间。

  3. 使用 AI Profiling 工具分析通信时间占比。

通常在多节点(2 个以上)、模型参数量较大(数十亿参数以上)的场景下,eRDMA 的性能提升最为明显。

Arena 提交作业失败,提示资源不足怎么办?

可能的原因包括:

  • GPU 或 eRDMA 资源不足。

  • 节点不满足调度条件(如节点选择器、污点容忍)。

解决方法:

  1. 执行 kubectl get nodes 查看节点状态和可用资源。

  2. 执行 kubectl describe pod <pod名> 查看 Pod 调度失败的详细原因。

  3. 根据提示调整资源请求或增加节点。

Arena提交作业核心参数说明。

参数

说明

建议配置

--name

作业名称,集群内全局唯一

使用具有业务含义的名称

--namespace

作业所属的命名空间

根据团队或项目隔离

--workers

Worker 节点数量(包含 Master)

设置为 2 表示 1 个 Master + 1 个 Worker

--gpus

每个 Worker 使用的 GPU 卡数

根据模型大小和显存需求设置

--device=aliyun/erdma=1

启用 eRDMA 的关键参数,为每个 Worker 分配 1 个 eRDMA 资源

必须设置为 1 以启用 eRDMA

--nproc-per-node

每个节点启动的训练进程数

通常设置为与 --gpus 相同

--clean-task-policy

Pod 清理策略

设置为 None 保留 Pod 以便查看日志

--env

环境变量

用于配置 NCCL 通信参数

NCCL 环境变量配置(用于优化分布式通信):

环境变量

说明

推荐配置

NCCL_SOCKET_IFNAME

指定用于通信的网卡接口

设置为 eth0(ACK 集群默认网卡)

NCCL_NET_GDR_LEVEL

GPU Direct RDMA 策略等级(0-5)

eRDMA 场景下推荐设置为 1(PIX 级别)

NCCL_P2P_LEVEL

点对点通信策略(0-5)

设置为 5(SYS 级别)支持跨节点通信

NCCL_ALGO

集合通信算法

可选 RingTree 等,根据网络拓扑选择

NCCL_DEBUG

日志级别

调试时设置为 INFO,生产环境可改为 WARN

NCCL_IB_HCA

指定使用的 RDMA 网卡

通过 ibstat 查看可用网卡名称

NCCL_IB_TIMEOUT

IB 通信超时时间

根据网络延迟调整

NCCL_IB_RETRY_CNT

IB 通信失败重试次数

不稳定网络可适当增加

更多 NCCL 环境变量说明,请参见 NCCL 官方文档

如何构建生产环境支持 eRDMA 的容器镜像?

使用 eRDMA 需要在容器中安装 RDMA 用户态库和驱动。以下 Dockerfile 示例基于 PyTorch 官方镜像,集成了 eRDMA 驱动程序和 MNIST 训练示例

构建生产环境支持 eRDMA 的容器镜像,更多信息,请参见在容器(Docker)中启用eRDMA
ARG PYTORCH_IMAGE=docker.io/pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime

FROM docker.io/library/alpine:3.22.1 AS downloader

WORKDIR /workspace

RUN apk add git wget gzip

RUN mkdir -p /workspace/MNIST/raw && \
    cat <<EOF > /workspace/MNIST/raw/checksums.md5
f68b3c2dcbeaaa9fbdd348bbdeb94873 train-images-idx3-ubyte.gz
d53e105ee54ea40749a09fcbcd1e9432 train-labels-idx1-ubyte.gz
9fb629c4189551a2d022fa330f9573f3 t10k-images-idx3-ubyte.gz
ec29112dd5afa0611ce80d1b7f02629c t10k-labels-idx1-ubyte.gz
EOF

RUN cd /workspace/MNIST/raw && \
    wget https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz && \
    wget https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz && \
    wget https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz && \
    wget https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz && \
    md5sum -c checksums.md5 && \
    rm checksums.md5 && \
    gzip -d *.gz

RUN git clone https://github.com/kubeflow/arena.git -b v0.15.2

FROM ${PYTORCH_IMAGE}

WORKDIR /workspace

COPY --from=downloader /workspace .

RUN set -eux && \
    apt update && \
    apt install -y wget gpg && \
    wget -qO - https://mirrors.aliyun.com/erdma/GPGKEY | gpg --dearmour -o /etc/apt/trusted.gpg.d/erdma.gpg && \
    echo "deb [ ] https://mirrors.aliyun.com/erdma/apt/ubuntu jammy/erdma main" > /etc/apt/sources.list.d/erdma.list && \
    apt update && \
    apt install -y libibverbs1 ibverbs-providers ibverbs-utils librdmacm1 && \
    pip install --no-cache-dir -r /workspace/arena/examples/pytorch/mnist/requirements.txt && \
    rm -rf /var/lib/apt/lists/*