当前位置: 首页 > backend >正文

NCCL 通信与调试

代码仓库

https://github.com/NVIDIA/nccl-tests

代码编译

编译 nccl-tests (MPI 版本): ”

编译支持 MPI 的 nccl-tests 是整合 nvcc, mpicc 和 NCCL 库的关键步骤

  1. 初始编译命令 (基于 README):

    cd /path/to/your/nccl-tests # 进入源码目录
    make clean
    make MPI=1 CUDA_HOME=... NCCL_HOME=... MPI_HOME=/path/to/shared/mpi 
    
  2. 问题遭遇 #1: fatal error: mpi.h: No such file or directory

    • 原因: 编译器 (nvcc 或其调用的 g++) 找不到 mpi.h。虽然 MPI_HOME 设置了,但 Makefile 可能没有正确地将 -I$(MPI_HOME)/include 添加到编译 .cu 文件的 NVCCFLAGS 中。
    • 尝试的解决方案 (可能无效):make 命令后添加 CFLAGS="-I/path/to/mpi/include" LDFLAGS="-L/path/to/mpi/lib"。但这可能因为 Makefile 内部变量优先级而失效。
    • 最终解决方案: 直接修改 src/Makefile。找到编译 .cu 文件的规则(通常包含 $(NVCC) ... -c $< -o $@),在 $(NVCUFLAGS) 或编译命令中显式添加 MPI 头文件路径:
      # 修改 src/Makefile 中编译 .cu 的行
      $(NVCC) -o $@ $(NVCUFLAGS) -I/path/to/shared/mpi/include -c $< 
      
    • 修改后,返回上层目录,重新执行 make clean 和步骤 1 中的 make 命令。
  3. (可能遇到的) 问题 #2: 链接时报 Unknown option '-pthread'-Wl,-rpath

    • 原因: 如果 Makefile 内部(或你错误地)将 mpicc --showme:link 的原始输出(包含 -pthread-Wl,...)直接传递给了 nvcc
    • 解决方案:
      • 检查 Makefile: 确保 Makefile 没有直接使用 $(shell mpicc --showme:link)。它应该只使用 MPI_HOME 来推断 -L-l 参数,或者你之前在 LDFLAGS 中只提供了 -L 路径。
      • 手动指定链接参数 (如果必须): 如果 Makefile 没有正确处理 MPI 链接,你需要:
        1. 运行 mpicc --showme:link
        2. 提取必要的 -L/path/to/mpi/lib-lmpi (及其他 libmpi* 依赖库)。
        3. 提取必要的链接器选项,如 -rpath, --enable-new-dtags
        4. make 命令中通过 LDFLAGS="..."-L-l 参数传递进去。
        5. 编辑 src/Makefile,找到最终链接生成可执行文件 (%_perf) 的 nvcc 命令那一行。
        6. 使用 -Xlinker 将提取的链接器选项(如 -rpath, 路径, --enable-new-dtags逐个添加到该行的 $(NVLDFLAGS) 之后。例如:
          # 修改 src/Makefile 中链接可执行文件的行
          $(NVCC) -o $@ $(NVCUFLAGS) $^ ${NVLDFLAGS} -Xlinker -rpath -Xlinker /path/to/shared/mpi/lib -Xlinker --enable-new-dtags
          

经过这些调整,MPI 版本的 nccl-tests 应该能成功编译出来。

运行双节点测试

  1. 设置无密码 SSH: 确保 Node A 和 Node B 之间可以互相进行无密码 SSH 登录 (使用 ssh-keygenssh-copy-id)。这是 mpirun 远程启动进程的前提。
    具体的命令为:ssh-keygen -t rsa生成密钥,ssh-copy-id root@ip地址 拷贝到另外一个服务器节点,使用ssh root@172.21.33.14 date测试是否成功免密登录。输出日期则成功设置免密。

  2. 最终的 mpirun 命令:

    # 确保环境已激活
    source /path/to/your/setup_env.sh # 执行 mpirun (替换 IP/主机名和路径)
    mpirun -np 2 \--prefix /path/to/shared/mpi \-host nodeA_ip,nodeB_ip \-bind-to none \-x PATH \-x LD_LIBRARY_PATH \-x NCCL_DEBUG=INFO \-x LD_PRELOAD="" \/path/to/your/nccl-tests/build/all_reduce_perf -b 8 -e 1G -f 2 -g 1 -a 1
    
    • -np 2: 启动 2 个进程,是我们要测试的场景。
    • --prefix ...: 帮助 mpirun 在远程节点找到 orted
    • -host ...: 指定两个目标节点。
    • -bind-to none: 避免不必要的 CPU 绑定。
    • -x PATH -x LD_LIBRARY_PATH: 极其重要! 尝试将包含本地 CUDA/NCCL/MPI 路径的环境变量传播到远程进程。验证传播是否成功是调试的关键(可以通过在程序早期打印环境变量来检查)。
    • -x NCCL_DEBUG=INFO: 启用 NCCL 详细日志,用于分析通信细节。
    • -x LD_PRELOAD="": 极其重要! 覆盖 /etc/ld.so.preload,禁用干扰库。
    • /path/to/.../all_reduce_perf: 指向编译好的 MPI 版本测试程序。
    • -b 8 -e 1G -f 2: 设置测试消息大小范围 (8B to 1GB, factor 2)。
    • -g 1: 核心设置! 每个 MPI 进程只使用 1 个 GPU,强制 NCCL 通过网络进行通信,从而测试节点间带宽。
    • -a 1: 报告平均性能。

结果解读

成功运行后,输出包含丰富的信息:

  1. 环境与设备确认 (开头注释与日志):

    • 验证 Rank 数量 (2)、节点数量 (2)、每个进程的 GPU 数量 (1) 是否正确。
    • 确认进程是否运行在预期的不同节点上,并使用了正确的 GPU 设备 (NVIDIA A30)。
    • 确认 CUDA 和 NCCL 版本是否一致且正确 (12.4 和 2.26.2)。
  2. NCCL 初始化日志 (NCCL INFO):

    • 网络选择: 关键看 Using network ... 行。我们的结果显示 Using network IB,证明 NCCL 成功选择了 InfiniBand。如果显示 Using network Socket,则表示回退到了以太网 TCP。
    • IB 细节: NET/IB : Using [0]mlx5_0:1/IB ... 显示了使用的具体 IB 设备和端口。
    • 初始化成功: 两个 Rank 都应输出 ncclCommInitRank ... Init COMPLETE
    • 拓扑信息: nRanks 2 nNodes 2 确认了跨节点。MNNVL 0 暗示未使用多节点 NVLink (通常需要特定硬件)。intraNodeP2pSupport 0 确认了节点内无 P2P。
  3. NCCL 运行时日志 (NCCL INFO):

    • Channel ... via NET/IB/1: 再次确认数据传输路径是 InfiniBand。
    • Connected all rings, use ring PXN 0 GDR 0:
      • ring: 使用了 Ring AllReduce 算法。
      • PXN 0: 通信主要走网络(而非节点内 P2P/NVLink)。
      • GDR 0: GPUDirect RDMA 未启用。 这意味着数据路径可能是 GPU -> CPU(Pinned) -> NIC -> Network -> NIC -> CPU(Pinned) -> GPU,而非最高效的 GPU -> NIC -> Network -> NIC -> GPU。这是未来可能的优化点,但需要检查硬件/驱动/系统配置。
  4. 性能表格分析:

    • #wrong 列: 必须为 0,确保结果正确性。
    • 核心指标 busbw (GB/s): 关注大消息(如 128MB - 1GB)下的饱和带宽。
    • 结果解读: 我们的测试中,峰值 busbw 稳定在 11 GB/s 左右。
    • 性能评估:
      • 单位换算: 100 Gbps (EDR InfiniBand 理论线速率) ≈ 12.5 GB/s (理论数据吞吐量)。
      • 比较: 实测 11 GB/s 非常接近 EDR IB 的理论可用吞吐量,表明 InfiniBand 网络工作正常且性能良好。远超普通千兆以太网 (~0.12 GB/s)。
      • 与预期偏差: 如果你的 IB 卡是更高速率的(如 HDR 200Gbps ≈ 25 GB/s),那么 11 GB/s 就偏低,可能原因包括交换机瓶颈、配置问题、或者未启用 GDR 的影响。
        好的,我们来逐一解答你的疑问,并理清 InfiniBand、PCIe、TCP/IP 在节点间通信中的角色和速率问题。

什么是 EDR InfiniBand?

  • InfiniBand (IB): 是一种高性能、低延迟的计算机网络通信标准,主要用于高性能计算 (HPC)、数据中心和存储网络。它与我们常用的以太网 (Ethernet) 是不同的技术体系。
  • 速率等级: InfiniBand 有不同的速率等级,通过缩写词表示:
    • SDR (Single Data Rate): 理论带宽 10 Gbps
    • DDR (Double Data Rate): 理论带宽 20 Gbps
    • QDR (Quad Data Rate): 理论带宽 40 Gbps
    • FDR (Fourteen Data Rate): 理论带宽 56 Gbps
    • EDR (Enhanced Data Rate): 理论带宽 100 Gbps
    • HDR (High Data Rate): 理论带宽 200 Gbps
    • NDR (Next Data Rate): 理论带宽 400 Gbps
    • XDR (Extreme Data Rate): 理论带宽 800 Gbps (及更高)
http://www.xdnf.cn/news/2592.html

相关文章:

  • Grok发布了Grok Studio 和 Workspaces两个强大的功能。该如何使用?如何使用Grok3 API?
  • 深度学习与SLAM特征提取融合:技术突破与应用前景
  • 深入解读:2025 数字化转型管理 参考架构
  • 视频HLS分片与关键帧优化深度解析
  • 2025 网络安全技术深水区探索:从 “攻防对抗” 到 “数字韧性” 的范式跃迁
  • VRRP与BFD在冗余设计中的核心区别:从“备用网关”到“毫秒级故障检测”
  • JavaScript中主动抛出错误的方法
  • 【java】lambda表达式总结
  • 类-python
  • AI中Token的理解与使用总结
  • seededit: Align image re-generation to image editing
  • 【中级软件设计师】编译和解释程序的翻译阶段、符号表 (附软考真题)
  • RC吸收电路参数设置实战
  • DJL FastText (FtModel) 使用指南
  • 如何编写企业的数据标准管理办法
  • 人大金仓sys_rman备份脚本
  • 【SAP-CO】标准价(S价)和移动平均价(V价)
  • 合理布局结构体,精打细算 cacheline
  • 设计并实现一个基于 Java + Spring Boot + MySQL 的通用多租户权限系统
  • 计算机网络-运输层(1)
  • 关闭浏览器的拼写检查
  • 低调使用,“黑神话”正确打开方式
  • Aloudata Agent 36 问,深度解惑!
  • 磁盘清理git gc
  • 服务器异地备份,服务器异地备份有哪些方法?
  • 记录学习记录学习《手动学习深度学习》这本书的笔记(九)
  • MVCC(多版本并发控制)
  • docker部署Mysql8一直密码错误记录
  • 实时操作系统在金融科技中的应用及未来展望
  • Coding Practice,48天强训(25)