附录 D – 如何使用自动配置的 IPv6 地址运行 NCCL 测试
要使用静态或通过 SLAAC 自动分配的全局 IPv6 地址运行模型或 NCCL 测试,必须调整 NCCL_IB_GID_INDEX 变量的值。
从 NCCL 2.21 开始,不再需要手动指定 GID 索引。它会根据NCCL_SOCKET_FAMILY设置自动处理。如果NCCL_SOCKET_FAMILY设置为AF_INET6,并且主机之间已建立 IPv6 连接,则通过 IPv6 的 RoCEv2 流量应按预期运行。
NCCL_IB_GID_INDEX 变量定义 RoCE (RDMA) 通信使用的全局 ID 索引。默认值为 -1,这意味着 NCCL 将根据 InfiniBand 设备的活动链路层自动选择正确的 GID 索引。如果链路层是以太网 (RoCE),NCCL 将使用返回支持 RoCE v2 的 GID(通常为 GID 索引 3,具体取决于驱动程序/固件)的 GID 索引。
有关更多详细信息,您可以查看 Nvidia 的环境变量文档
要查找所需地址的 GID,请使用以下命令:
ibv_devinfo -vvv -d <mellanox-interface-name> | grep GID
要查找 mellanox 接口名称,您可以使用以下脚本:
jnpr@H100-01:~/scripts$ cat nvidia_map_iface_to_mlx.sh
# Script to map network interfaces to Mellanox interfaces
echo "Network Interface to Mellanox Interface Mapping:"
# Loop through each network interface in /sys/class/net/
for iface in $(ls /sys/class/net/); do
if [ -d /sys/class/net/$iface/device/infiniband_verbs ]; then
# Find the Mellanox interface by reading the ibdev file
mlx_iface=$(cat /sys/class/net/$iface/device/infiniband_verbs/*/ibdev)
echo "$iface => $mlx_iface"
fi
done
示例:
jnpr@H100-01:/etc/netplan$ ibv_devinfo -vvv -d mlx5_6 | grep GID GID[ 0]: fe80:0000:0000:0000:a288:c2ff:fe3b:506a, RoCE v1 GID[ 1]: fe80::a288:c2ff:fe3b:506a, RoCE v2 GID[ 2]: 0000:0000:0000:0000:0000:ffff:0ac8:010a, RoCE v1 GID[ 3]: ::ffff:10.200.1.10, RoCE v2 GID[ 4]: FC00:200:0000:0002:a288:c2ff:fe3b:506a, RoCE v1 GID[ 5]: FC00:200:0:2:a288:c2ff:fe3b:506a, RoCE v2 jnpr@H100-01:~/scripts$ ./nvidia_map_iface_to_mlx.sh | egrep "gpu|Map" Network Interface to Mellanox Interface Mapping: gpu0_eth => mlx5_11 gpu1_eth => mlx5_6 gpu2_eth => mlx5_10 gpu3_eth => mlx5_9 gpu4_eth => mlx5_4 gpu5_eth => mlx5_3 gpu6_eth => mlx5_5 gpu7_eth => mlx5_0
可以使用脚本 find_pxb_gpu_nic_pairs.py 轻松找到 Mellanox 接口名称、用户分配的接口名称(例如 gpu0_eth)、NIC 和 GPU 之间的映射信息,这些信息可在以下位置 找到: https://github.com/Juniper/jvd/tree/main/Data%20Center/AIDC/backend/AI_ML_Multitenancy
示例:
jnpr@H100-01:~/SCRIPTS$ python3 find_pxb_gpu_nic_pairs.py Running full GPU↔NIC mapping workflow... Collecting GPU-NIC topology via nvidia-smi... Converting raw_topo.txt → topo.csv ... Parsing topo.csv and identifying PXB pairs... Detected GPU ↔ NIC (PXB) Pairs: GPU0 ←→ NIC0 GPU1 ←→ NIC3 GPU2 ←→ NIC4 GPU3 ←→ NIC5 GPU4 ←→ NIC6 GPU5 ←→ NIC9 GPU6 ←→ NIC10 GPU7 ←→ NIC11 Saved to pxb_gpu_nic_pairs.txt Building mlx5_X → NIC# mapping via mst status... mlx5_X ↔ NIC# Mapping: mlx5_0 ←→ NIC0 mlx5_1 ←→ NIC1 mlx5_2 ←→ NIC2 mlx5_3 ←→ NIC3 mlx5_4 ←→ NIC4 mlx5_5 ←→ NIC5 mlx5_6 ←→ NIC6 mlx5_7 ←→ NIC7 mlx5_8 ←→ NIC8 mlx5_9 ←→ NIC9 Saved to mlx-to-nic-map.txt Building gpuX_eth → NIC# mapping from PXB pairs... gpu0_eth ←→ NIC0 gpu1_eth ←→ NIC3 gpu2_eth ←→ NIC4 gpu3_eth ←→ NIC5 gpu4_eth ←→ NIC6 gpu5_eth ←→ NIC9 gpu6_eth ←→ NIC10 gpu7_eth ←→ NIC11 Saved to gpu_eth-to-nic.txt
确定 GID 后,您可以使用以下方法运行 NCCL 测试:
TENANT=<TENANT#> GID=<GID> ./run-tenant.sh
您也可以 在以下位置找到: https://github.com/Juniper/jvd/tree/main/Data%20Center/AIDC/backend/AI_ML_Multitenancy
示例:
jnpr@headend-svr-1:/mnt/nfsshare/source/aicluster/new-nccl$ TENANT=1 GID=5 ./run-tenant.sh The RAIL partition directory /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/ already exists ... Created SLURM logs directory /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10152025_19_16_31 ... === JOB SUMMARY ================================= TENANT = 1 NODES = 4 NODE_LIST = H100-01,H100-02,H100-03,H100-04 PARTITION = H100-RAILS-ALL LOGDIR = /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10152025_19_16_31 TEST = all_reduce_perf (bsize=16G, esize=16G, iters=10, agg_iters=1) GID input = 3(GID) (GID_INDEX) NCCL_IB_GID_INDEX = 3 UCX_IB_GID_INDEX = 3 ================================================== Submitted batch job 29713 jnpr@headend-svr-1:/mnt/nfsshare/source/aicluster/new-nccl$ cat /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10152025_19_16_31/slurm-29713.out|grep Avg [1,0]<stdout>: # Avg bus bandwidth : 47.669
要检查在运行 NCCL 测试时是否使用了正确的 GPU,请使用以下命令:
jnpr@H100-01:~/scripts$ cat show-gpu-procs.sh
#!/bin/bash
# show-gpu-procs.sh — display only the "Processes" section of nvidia-smi
set -euo pipefail
echo "| Processes: |"
echo "| GPU GI CI PID Type Process name GPU Memory |"
nvidia-smi | awk '/GPU GI/{flag=1;next}/^$/{flag=0}flag'
示例:
jnpr@headend-svr-1:/mnt/nfsshare/source/aicluster/new-nccl$ TENANT=1 GID=5 ./run-tenant.sh The RAIL partition directory /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/ already exists ... Created SLURM logs directory /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10162025_15_24_33 ... === JOB SUMMARY ================================= TENANT = 1 NODES = 4 NODE_LIST = H100-01,H100-02,H100-03,H100-04 PARTITION = H100-RAILS-ALL LOGDIR = /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10162025_15_24_33 TEST = all_reduce_perf (bsize=16G, esize=16G, iters=10, agg_iters=1) GID input = 5(GID) (GID_INDEX) NCCL_IB_GID_INDEX = 5 UCX_IB_GID_INDEX = 5 ================================================== Submitted batch job 29814 jnpr@headend-svr-1:/mnt/nfsshare/source/aicluster/new-nccl$ TENANT=2 GID=5 ./run-tenant.sh The RAIL partition directory /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/ already exists ... Created SLURM logs directory /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10162025_15_24_36 ... === JOB SUMMARY ================================= TENANT = 2 NODES = 4 NODE_LIST = H100-01,H100-02,H100-03,H100-04 PARTITION = H100-RAILS-ALL LOGDIR = /mnt/nfsshare/logs/new-nccl/H100-RAILS-ALL/10162025_15_24_36 TEST = all_reduce_perf (bsize=16G, esize=16G, iters=10, agg_iters=1) GID input = 5(GID) (GID_INDEX) NCCL_IB_GID_INDEX = 5 UCX_IB_GID_INDEX = 5 ================================================== Submitted batch job 29815 jnpr@H100-01:~/scripts$ sudo ./show-gpu-procs.sh | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=======================================================================================| | 4 N/A N/A 4120128 C nccl-tests/build/all_reduce_perf 51020MiB | | 7 N/A N/A 4119971 C nccl-tests/build/all_reduce_perf 51020MiB | +---------------------------------------------------------------------------------------+
GPU–NIC 映射和拓扑感知
确保将正确的 GPU 和 NIC 映射到每个租户。在分配的 GPU 和 NIC 之间保持 紧密的 NUMA 和 PCIe 对齐 可确保最佳性能。每个租户的 GPU 和 NIC 应尽可能战略性地位于 同一 NUMA 区域和 PCIe 层次结构中 。
nvidia-smi topo -m 命令显示系统中 GPU、NIC 和 CPU 之间的 互连拓扑 。输出显示为 矩阵 ,其中行和列代表设备,每个单元格表示它们之间的 连接类型 (或“距离”)。这些连接类型揭示了流量如何流经 PCIe 交换机、主机桥接器和 CPU 插槽,帮助确定哪些 GPU-NIC 配对提供最佳性能。
| X | 同一设备(矩阵的对角线) |
| 像素 | Single PCIe 交换机或桥接器。最短路径、最快通信 |
| PXB | 同一根复合体(NUMA 节点)中的 多个 PCIe 网桥 ,但不遍历 PCIe 主机网桥。路径和延迟稍长。 |
| PHB | 穿过 PCIe 主机桥 (连接到 CPU)。可能跨越 CPU 边界。性能较低。 |
| 系统 | 跨越同一 NUMA 节点内的多个 PCIe 主机桥。延迟增加。 |
| 节点 | 跨 NUMA 节点,遍历 CPU 套接字之间的 QPI/UPI 互连 。最慢路径 — 避免用于 RDMA 或延迟敏感型流量。 |
对于 RDMA 流量,请为 GPU↔NIC 对选择 PXB 或 PIX 路径,以在同一 NUMA 域和 PCIe 主机桥接器内保持通信。尽可能避免使用 SYS 或 NODE 路径,因为它们会增加不必要的延迟并降低带宽效率。
例如,考虑将 GPU2 和 NIC0 分配给租户 A,将 GPU5 和 NIC9 分配给租户 B 的情况,如下图所示。图 ## 中的 nvidia-smi topo -m 输出表示,来自 GPU2→NIC0 的流量必须遍历多个 PCIe 主机桥接并跨越 NUMA 域,这会导致租户 A 的性能下降。相比之下,GPU5→NIC9 通过同一根复合体内的多个 PCIe 网桥进行通信,避免了 CPU 遍历并为租户 B 保持了更好的性能。
图 61.租户 GPU 和 NIC 分配示例