尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

cuML 多节点多 GPU(MNMG)集群启用 InfiniBand 通信的完整配置指南

cuML 多节点多 GPU(MNMG)集群启用 InfiniBand 通信的完整配置指南 cuML 多节点多 GPUMNMG集群启用 InfiniBand 通信的完整配置指南【免费下载链接】cumlNVIDIA cuML: GPU-Accelerated Machine Learning项目地址: https://gitcode.com/GitHub_Trending/cu/cuml[!WARNING] 本文所述步骤源自 cuML 仓库 wiki/mnmg/Using_Infiniband_for_MNMG.md该页面明确标注为弃用deprecated其中的命令与 API 面向早期版本UCX/CUDA 9.2 时代编写无法直接用于最新版 cuML。本文保留其完整技术脉络供理解 MNMG 通信原理与历史演进并在文末给出与当前仓库源码的差异对照帮助读者正确迁移到新版 API。若要在生产环境部署请以当前版本官方文档为准。导读cuML 的多节点多 GPUMulti-Node Multi-GPUMNMG训练依赖 Dask 在多个计算节点之间协调 GPU 数据交换。当节点间通过传统 TCP/IP 以太网互联时PCIe/网络带宽往往成为大规模训练的瓶颈而 InfiniBand 提供的 RDMARemote Direct Memory Access能力可以让数据在 GPU 显存、主机内存与网卡之间以远高于 TCP 的带宽和远低于 CPU 的参与度直接传输。本文围绕 cuML 仓库中的历史运维文档系统讲解从安装 UCX、编译 gdrcopy、配置 NCCL、启用 IP over IB到启动 UCX 协议 Dask 集群、并在 cuML/RAFT 通信层上完成点对点P2P与集合通信Allreduce连通性测试的完整闭环让你理解 MNMG 场景下 InfiniBand 的每一层配置细节与验证方法。1. MNMG 通信架构概览为什么需要 InfiniBandcuML 的 MNMG 实现见 python/cuml/cuml/dask 目录下的cluster、linear_model、decomposition、neighbors等子模块采用「Dask 负责任务调度、底层通信库负责 GPU 间数据交换」的两层架构Dask负责将算法分解为跨节点的任务图并把数据分片调度到各个 worker通信层历史上为 UCX NCCL当前仓库中由 RAPIDS 的 raft-dask 提供Comms封装负责 worker 之间真正的 GPU 张量交换包括点对点 send/recv 与集合 allreduce。当训练数据需要跨节点聚合例如 KMeans 的中心点同步、DBSCAN 的标签合并、PCA 的协方差归约时节点间通信量会随规模快速增长。InfiniBand 相比以太网的核心优势在于RDMA 卸载数据从 GPU 显存经 GPUDirect RDMA 直达网卡无需经过 CPU 内存拷贝降低延迟与 CPU 占用高带宽低延迟文档示例环境为 100 Gb/sec4X EDR链路远超当时常见千兆/万兆以太网内核旁路绕过操作系统网络协议栈减少中断与上下文切换开销。在 cuML 中跨节点通信的初始化与测试入口正是文档第 7 节使用的Comms对象——它管理一个跨所有 Dask worker 的通信会话session并为每个 worker 建立 Raft 通信句柄handle。后续所有 MNMG 算法都会复用该句柄执行聚合操作。2. 安装 UCXUnified Communication XUCX 是本文方案最底层的通信库它统一封装了 InfiniBandrc/ud等 RDMA 传输、CUDA 内存拷贝cuda_copy、cuda_ipc与 GPUDirect RDMAgdr_copy等多种传输通道。cuML 的 MNMG 通过 UCX 建立 Dask worker 之间的底层数据通路。注意原文提示该 conda 包当时处于实验阶段最终会由 rapidsai 频道提供支持当时需要 CUDA 9.2CUDA 10 包也在开发中。2.1 通过 Conda 安装conda install -c conda-forge -c jakirkham/label/ucx cudatoolkit9.2 ucx-proc*gpu ucx python3.7关键参数说明参数含义cudatoolkit9.2与当时 cuML 依赖的 CUDA 工具链版本对齐ucx-proc*gpu选择启用 CUDA/GPU 支持的 UCX 构建变体而非仅 CPU 版python3.7锁定 Python 版本以匹配当时 rapidsai 生态2.2 从源码编译当 conda 渠道没有可用的实验包时可以自行编译。首先安装编译工具链sudo apt-get install autogen autoconf libtool可选安装 gdrcopy 以加速 GPU 与网卡间的数据搬运根据 UCX 的 NVIDIA GPU 支持文档安装gdrcopy可以并且可能有必要启用更快的 GPU-网卡数据搬运。gdrcopy 提供了一套让 CPU 端代码可以直接读写 GPU 显存的库UCX 借助它实现gdr_copy传输git clone https://github.com/NVIDIA/gdrcopy.git cd gdrcopy make -j PREFIX$CONDA_INSTALL_PREFIX CUDA/usr/local/cuda make -j install sudo ./insmod.sh其中PREFIX指定安装前缀示例指向 conda 环境CUDA指向 CUDA 安装目录insmod.sh用于加载内核模块。编译带 CUDA 与多线程支持的 UCXgit clone https://github.com/cjnolet/ucx-py.git cd ucx git checkout fea-ext-expose_worker_and_ep ./autogen.sh mkdir build cd build ../configure --prefix$CONDA_PREFIX --with-cuda/usr/local/cuda --enable-mt --disable-cma CPPFLAGS-I//usr/local/cuda/include make -j install配置选项说明选项作用--prefix$CONDA_PREFIX安装到当前 conda 环境便于后续 ucx-py 通过UCX_PATH找到它--with-cuda/usr/local/cuda启用 CUDA 支持编译出cuda_copy/cuda_ipc传输--enable-mt启用多线程安全支持--disable-cma禁用 cross-memory attach避免与 CUDA 注册内存的兼容问题--with-gdrcopy/path/to/gdrcopy若已安装 gdrcopy追加该选项即可启用gdr_copy传输2.3 验证 UCX 传输能力ucx_info -d编译完成后用ucx_info -d列出所有可用传输。应当能看到rcInfiniBand Reliable Connection传输例如# Transport: rc # # Device: mlx5_0:1 # # capabilities: # bandwidth: 11794.23 MB/sec # latency: 600 nsec 1 * N # overhead: 75 nsec # put_short: 124 # put_bcopy: 8K # put_zcopy: 1G, up to 8 iov # put_opt_zcopy_align: 512 # put_align_mtu: 4K # get_bcopy: 8K # get_zcopy: 65..1G, up to 8 iov # get_opt_zcopy_align: 512 # get_align_mtu: 4K # am_short: 123 # am_bcopy: 8191 # am_zcopy: 8191, up to 7 iov # am_opt_zcopy_align: 512 # am_align_mtu: 4K # am header: 127 # domain: device # connection: to ep # priority: 30 # device address: 3 bytes # ep address: 4 bytes # error handling: peer failure同时应看到 CUDA 相关传输。cuda_copy用于 CPU 内存与 GPU 显存之间的拷贝# Transport: cuda_copy # # Device: cudacopy0 # # capabilities: # bandwidth: 6911.00 MB/sec # latency: 10000 nsec # overhead: 0 nsec # put_short: 4294967295 # put_zcopy: unlimited, up to 1 iov # put_opt_zcopy_align: 1 # put_align_mtu: 1 # get_short: 4294967295 # get_zcopy: unlimited, up to 1 iov # get_opt_zcopy_align: 1 # get_align_mtu: 1 # connection: to iface # priority: 0 # device address: 0 bytes # iface address: 8 bytes # error handling: nonecuda_ipc用于同一节点内跨进程的 GPU 显存共享通过 CUDA IPC 机制# Memory domain: cuda_ipc # component: cuda_ipc # register: 1G, cost: 0 nsec # remote key: 104 bytes # # Transport: cuda_ipc # # Device: cudaipc0 # # capabilities: # bandwidth: 24000.00 MB/sec # latency: 1 nsec # overhead: 0 nsec # put_zcopy: 1G, up to 1 iov # put_opt_zcopy_align: 1 # put_align_mtu: 1 # get_zcopy: 1G, up to 1 iov # get_opt_zcopy_align: 1 # get_align_mtu: 1 # connection: to iface # priority: 0 # device address: 8 bytes # iface address: 4 bytes # error handling: none若在configure时指定了--with-gdrcopy列表中还会出现gdr_copy传输它让数据可以直接从 GPU 显存经由 GPUDirect RDMA 搬运到 InfiniBand 网卡# Memory domain: gdr_copy # component: gdr_copy # register: unlimited, cost: 0 nsec # remote key: 32 bytes # # Transport: gdr_copy # # Device: gdrcopy0 # # capabilities: # bandwidth: 6911.00 MB/sec # latency: 1000 nsec # overhead: 0 nsec # put_short: 4294967295 # get_short: 4294967295 # connection: to iface # priority: 0 # device address: 0 bytes # iface address: 8 bytes # error handling: none判读要点确认列表同时包含rc跨节点 IB、cuda_ipc节点内 GPU 共享与cuda_copyCPU/GPU 拷贝若配置了 gdrcopy 还应看到gdr_copy。缺少任何一项都意味着对应数据通路不可用后续 Dask 集群将退化为较低效的传输组合。3. 安装 ucx-py把 UCX 暴露给 Python/Daskucx-py是 UCX 的 Python 绑定它把 UCX worker/endpoint 暴露给 Python 层是 Dask 的ucx://协议得以工作的桥梁。3.1 通过 Conda 安装conda install -c conda-forge -c jakirkham/label/ucx cudatoolkit9.2 ucx-py python3.73.2 从源码安装git clone gitgithub.com:rapidsai/ucx-py cd ucx-py export UCX_PATH$CONDA_PREFIX make -j installUCX_PATH必须指向第 2 节中 UCX 的安装前缀即--prefix指定的路径这样 ucx-py 才能在运行时定位到 UCX 库。4. 安装并配置 NCCLNCCLNVIDIA Collective Communications Library负责 cuML MNMG 中的集合通信如 allreduce。原文特别强调必须安装 NCCL 2.4 及以上版本且库路径上不能残留旧版本 NCCL否则会在 cuML 构建阶段引发编译错误。conda install -c nvidia nccl随后在主目录创建.nccl.conf把 NCCL 的 socket 接口绑定到 InfiniBand 设备ib0NCCL_SOCKET_IFNAMEib0这一步确保 NCCL 的集合通信流量走 IB 接口而非默认的以太网接口与第 5 步中 UCX 的接口选择保持一致。5. 为 IB 设备启用 IP over IB 接口ib0NCCL 与 Dask 的控制面通信需要 IP 地址因此需要在 InfiniBand 设备上启用 IP over IB。当 IP over IB 内核模块已经安装好后把 IB 设备映射到 IP 接口非常简单sudo ifconfig ib0 10.0.0.50/24用ifconfig ib0验证接口是否创建正确输出形如ib0 Link encap:UNSPEC HWaddr 80-00-00-68-FE-80-00-00-00-00-00-00-00-00-00-00 inet addr:10.0.0.50 Bcast:10.0.0.255 Mask:255.255.255.0 inet6 addr: fe80::526b:4b03:f5:ce9c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:65520 Metric:1 RX packets:2655 errors:0 dropped:0 overruns:0 frame:0 TX packets:2697 errors:0 dropped:10 overruns:0 carrier:0 collisions:0 txqueuelen:256 RX bytes:183152 (183.1 KB) TX bytes:194696 (194.6 KB)注意MTU:65520正是 InfiniBand 的大 MTU相比以太网 1500 字节这也是 IB 高吞吐的来源之一。每个节点都需要为各自的 IB 设备配置 IP例如本例中 scheduler 节点使用10.0.0.50其他节点使用同一子网内的不同地址。6. 设置 UCX 环境变量先运行ibstatus查看本机可用的 IB 设备及端口状态Infiniband device mlx5_0 port 1 status: default gid: fe80:0000:0000:0000:506b:4b03:00f5:ce9c base lid: 0xf sm lid: 0x1 state: 4: ACTIVE phys state: 5: LinkUp rate: 100 Gb/sec (4X EDR) link_layer: InfiniBand Infiniband device mlx5_1 port 1 status: default gid: fe80:0000:0000:0000:506b:4b03:0049:4236 base lid: 0x6 sm lid: 0x1 state: 4: ACTIVE phys state: 5: LinkUp rate: 100 Gb/sec (4X EDR) link_layer: InfiniBand Infiniband device mlx5_2 port 1 status: default gid: fe80:0000:0000:0000:506b:4b03:00f5:cf04 base lid: 0x2 sm lid: 0x1 state: 4: ACTIVE phys state: 5: LinkUp rate: 100 Gb/sec (4X EDR) link_layer: InfiniBand Infiniband device mlx5_3 port 1 status: default gid: fe80:0000:0000:0000:506b:4b03:0049:3eb2 base lid: 0x11 sm lid: 0x1 state: 4: ACTIVE phys state: 5: LinkUp rate: 100 Gb/sec (4X EDR) link_layer: InfiniBand关键状态判读state: 4: ACTIVE与phys state: 5: LinkUp表示端口已激活并完成链路协商rate: 100 Gb/sec (4X EDR)给出链路速率。把设备与端口写入UCX_NET_DEVICES指定 UCX 实际使用的 IB 设备列表export UCX_NET_DEVICESmlx5_0:1,mlx5_3:1,mlx5_2:1,mlx5_1:1设置 UCX 启用的传输TLStransport layer selectionexport UCX_TLSrc,cuda_copy,cuda_ipcrc跨节点的 InfiniBand Reliable Connection是节点间 GPU 数据交换的主力通道cuda_copyCPU/GPU 内存拷贝传输作为非 RDMA 路径的兜底cuda_ipc节点内跨进程 GPU 显存共享。注意若安装了gdrcopy需把gdr_copy追加到UCX_TLS末尾即export UCX_TLSrc,cuda_copy,cuda_ipc,gdr_copy以启用 GPU 显存直达 IB 网卡的 GPUDirect RDMA 路径。这些环境变量需要**在启动 Dask 的每个节点上scheduler 与所有 worker**预先导出并随进程传递给 Dask 运行时。7. 在 ib0 接口上启动 Dask 集群在作为调度器scheduler的节点上运行dask-scheduler --protocol ucx --interface ib0--protocol ucx让 Dask 使用 UCX 作为通信协议而非默认的 TCP--interface ib0绑定到 IP over IB 接口确保控制面与数据面流量都走 IB。然后在每个 worker 节点上启动 GPU worker连接地址使用 scheduler 的 IP over IB 地址示例中为10.0.0.50端口为 Dask 默认的 8786dask-cuda-worker ucx://10.0.0.50:8786dask-cuda-worker是 RAPIDS 生态提供的 GPU 感知 worker它会为每个 GPU 启动一个 worker 进程并在启动阶段初始化 UCX 与 NCCL 环境。8. 验证通信cumlCommunicator 测试集群就绪后用一段 Python 脚本创建 DaskClient与 cuML 的Comms通信会话然后分别测试点对点P2P与集合Allreduce通信。8.1 创建 Client 与 Commsfrom dask.distributed import Client, wait from cuml.raft.dask.common.comms import Comms from cuml.dask.common import get_raft_comm_state from cuml.dask.common import perform_test_comms_send_recv from cuml.dask.common import perform_test_comms_allreduce import random c Client(ucx://10.0.0.50:8786) cb Comms(comms_p2pTrue) cb.init()Client(ucx://10.0.0.50:8786)通过 UCX 协议连接 schedulerComms(comms_p2pTrue)创建跨 worker 的通信管理器comms_p2pTrue表示同时初始化点对点通信能力cb.init()在所有 worker 上建立 Raft 通信会话sessionId各 worker 可通过get_raft_comm_state(sessionId)获取通信句柄handle。8.2 测试点对点通信send/recvn_trials 2 def func_test_send_recv(sessionId, n_trials, r): handle get_raft_comm_state(sessionId)[handle] return perform_test_comms_send_recv(handle, n_trials) p2p_dfs[c.submit(func_test_send_recv, cb.sessionId, n_trials, random.random(), workers[w]) for wid, w in zip(range(len(cb.worker_addresses)), cb.worker_addresses)] wait(p2p_dfs) p2p_result list(map(lambda x: x.result(), p2p_dfs)) print(str(p2p_result)) assert all(p2p_result)该测试让每个 worker 通过 UCX 向其他所有 worker 发送/接收数据验证节点间的 RDMA 数据通路。worker 上应看到类似输出每个 Trial 中每个 rank 收到的数据集合恰好缺失自身 rank证明全连通且数据正确 Trial 0 Rank 0 received: [1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 1 received: [0, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 2 received: [0, 1, 3, 4, 5, 6, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 3 received: [0, 1, 2, 4, 5, 6, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 4 received: [0, 1, 2, 3, 5, 6, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 5 received: [0, 1, 2, 3, 4, 6, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 6 received: [0, 1, 2, 3, 4, 5, 7, 10, 11, 12, 13, 8, 9, 14, 15] Rank 7 received: [0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 8, 9, 14, 15] Trial 1 Rank 0 received: [11, 2, 13, 12, 9, 10, 15, 14, 1, 8, 5, 4, 3, 6, 7] Rank 1 received: [2, 12, 11, 10, 9, 14, 13, 8, 15, 4, 5, 6, 3, 0, 7] Rank 2 received: [12, 1, 11, 10, 9, 14, 13, 8, 15, 4, 5, 6, 3, 0, 7] Rank 3 received: [2, 11, 12, 10, 9, 14, 13, 8, 15, 4, 1, 6, 5, 0, 7] Rank 4 received: [2, 11, 12, 9, 13, 10, 15, 14, 1, 8, 3, 6, 5, 0, 7] Rank 5 received: [2, 11, 12, 9, 10, 14, 13, 8, 15, 4, 1, 6, 3, 0, 7] Rank 6 received: [2, 11, 12, 9, 10, 13, 15, 14, 1, 8, 5, 4, 3, 0, 7] Rank 7 received: [2, 11, 12, 9, 10, 13, 14, 8, 15, 4, 1, 6, 5, 0, 3] 8.3 测试集合通信Allreducedef func_test_allreduce(sessionId, r): handle get_raft_comm_state(sessionId)[handle] return perform_test_comms_allreduce(handle) coll_dfs [c.submit(func_test_allreduce, cb.sessionId, random.random(), workers[w]) for wid, w in zip(range(len(cb.worker_addresses)), cb.worker_addresses)] wait(coll_dfs) coll_result list(map(lambda x: x.result(), coll_dfs)) coll_result assert all(coll_result)该测试通过 NCCL 在所有 worker 之间执行 allreduce 归约验证集合通信通路。worker 上应看到类似输出Clique size: 16 Clique size: 16 Clique size: 16 Clique size: 16 Clique size: 16 Clique size: 16 final_size: 16 Clique size: 16 Clique size: 16 final_size: 16 final_size: 16 final_size: 16 final_size: 16 final_size: 16 final_size: 16 final_size: 16Clique size表示参与归约的 rank 数量final_size: 16表示 16 个 rank示例为 8 节点 × 每节点多 GPU 或单节点多 GPU 的总数全部正确参与了归约。两个断言assert all(...)全部通过即代表 InfiniBand 数据通路配置成功可以在此基础上运行 cuML 的 MNMG 算法。9. 与当前仓库源码的差异API 演进对照原文档编写时使用的是cuml.raft.dask.common.comms等旧导入路径。在当前版本的 cuML 仓库中通信层已经迁移为独立的 raft-dask 库导入路径变为raft_dask.common.comms。以仓库源码为证python/cuml/cuml/dask/cluster/kmeans.py 使用from raft_dask.common.comms import Comms, get_raft_comm_statepython/cuml/cuml/dask/cluster/dbscan.py 同样导入Comms, get_raft_comm_statepython/cuml/cuml/dask/neighbors/nearest_neighbors.py、python/cuml/cuml/dask/decomposition/base.py、python/cuml/cuml/dask/common/base.py 等文件也统一使用raft_dask命名空间。因此原文档第 8 节测试脚本中perform_test_comms_send_recv/perform_test_comms_allreduce这两个函数在当前 cuML 源码中已不存在其对应能力由raft_dask提供的通信测试 API 承担。从源码结构看当前 MNMG 算法KMeans、DBSCAN、PCA、kNN、线性模型等统一通过get_raft_comm_state(sessionId)获取通信句柄再调用 raft 底层的comms完成聚合操作——这一「会话 句柄」的架构与文档第 8 节的测试逻辑一脉相承只是封装库与导入路径发生了变化。此外python/cuml/cuml/dask/common/utils.py 提供了parse_host_port、get_client、wait_and_raise_from_futures等 MNMG 通用工具python/cuml/cuml/tests/dask 目录下的测试如test_kmeans.py、test_pca.py与 CI 脚本 ci/run_cuml_dask_pytests.sh 展示了当前 MNMG 功能的验证方式可作为理解新版通信层用法的参考入口。10. 总结Infiniband 配置链路一览层级组件配置/验证要点传输库UCXconda 或源码安装ucx_info -d确认rc/cuda_copy/cuda_ipc/gdr_copyGPU 搬运gdrcopy可选编译安装后configure --with-gdrcopy启用gdr_copyPython 绑定ucx-pyUCX_PATH指向 UCX 前缀make -j install集合通信NCCL 2.4conda install -c nvidia nccl~/.nccl.conf设NCCL_SOCKET_IFNAMEib0网络接口IP over IBifconfig ib0 10.0.0.50/24ifconfig ib0确认 MTU 65520环境变量UCXUCX_NET_DEVICESmlx5_0:1,...UCX_TLSrc,cuda_copy,cuda_ipc[,gdr_copy]集群启动Daskdask-scheduler --protocol ucx --interface ib0dask-cuda-worker ucx://scheduler-ip:8786连通性验证Comms 测试P2P send/recv 与 Allreduce 测试断言全通过按此链路逐层验证即可在具备 InfiniBand 硬件的环境中为 cuML 的 MNMG 训练建立高带宽、低延迟的 GPU 间通信基础。再次提醒以上命令与 API 面向旧版本部署最新版 cuML 时应参考当前官方文档并将通信导入迁移至raft_dask.common.comms。【免费下载链接】cumlNVIDIA cuML: GPU-Accelerated Machine Learning项目地址: https://gitcode.com/GitHub_Trending/cu/cuml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表