故障排除¶
请确保您熟悉以下已知问题和有用的调试策略。
错误¶
NCCL 调用可能会返回各种返回代码。确保返回代码始终等于 ncclSuccess。如果任何调用失败并返回与 ncclSuccess 不同的值,则将 NCCL_DEBUG 设置为“WARN”将使 NCCL 在返回错误之前打印显式警告消息。
错误分为不同的类别。
- ncclUnhandledCudaError 和 ncclSystemError 表示对外部库的调用失败。
- ncclInvalidArgument 和 ncclInvalidUsage 表示在使用 NCCL 的应用程序中存在编程错误。
在任何一种情况下,请参阅 NCCL 警告消息以了解如何解决问题。
GPU Direct¶
NCCL 在很大程度上依赖 GPU Direct 进行 GPU 间通信。这指的是 GPU 使用直接点对点 PCI 消息直接与另一个设备(例如另一个 GPU 或网卡)通信的能力。
由于各种原因,直接点对点 PCI 消息可能会失败或性能不佳,例如缺少组件、虚拟机或容器配置错误或某些 BIOS 设置。
GPU 到 GPU 通信¶
为确保 GPU 到 GPU 通信正常工作,请查找 CUDA 示例中的 p2pBandwidthLatencyTest。
cd /usr/local/cuda/samples/1_Utilities/p2pBandwidthLatencyTest
sudo make
./p2pBandwidthLatencyTest
该测试应运行完成并报告 GPU 之间的良好性能。
另一个用于检查 GPU 到 GPU 性能的工具称为 nvbandwidth
。可以从此处找到的代码和说明下载和构建它:https://github.com/NVIDIA/nvbandwidth
GPU 到 NIC 通信¶
GPU 还可以使用 GPU Direct RDMA (GDRDMA) 直接与网卡通信。这需要具有兼容的网卡和驱动程序,以及加载一个名为 nvidia-peermem
的额外内核模块。nvidia-peermem
模块现在随 CUDA 驱动程序一起提供,但必须在每次节点启动时加载,使用
sudo modprobe nvidia-peermem
GDRDMA 也可以通过结合使用最新 Linux 内核的 DMA-BUF 功能和开源 Nvidia GPU 驱动程序来启用。在这种情况下,NCCL 将自动检测并启用 DMA-BUF,因此 nvidia-peermem 模块将不是必需的。
PCI 访问控制服务 (ACS)¶
裸机系统
IO 虚拟化(也称为 VT-d 或 IOMMU)可能会干扰 GPU Direct,方法是将所有 PCI 点对点流量重定向到 CPU 根复合体,从而导致性能显着降低甚至挂起。您可以通过运行以下命令检查 PCI 桥上是否启用了 ACS
sudo lspci -vvv | grep ACSCtl
如果行显示“SrcValid+”,则可能已启用 ACS。查看 lspci 的完整输出,可以检查 PCI 桥是否启用了 ACS。
sudo lspci -vvv
如果 PCI 交换机启用了 ACS,则需要禁用它。在某些系统上,可以通过在 BIOS 中禁用 IO 虚拟化或 VT-d 来完成。对于 Broadcom PLX 设备,可以在操作系统中完成,但每次重启后都需要重新完成。
使用以下命令查找 PLX PCI 桥的 PCI 总线 ID
sudo lspci | grep PLX
接下来,使用 setpci 使用以下命令禁用 ACS,将 03:00.0 替换为每个 PCI 桥的 PCI 总线 ID。
sudo setpci -s 03:00.0 ECAP_ACS+0x6.w=0000
或者您可以使用类似于此的脚本
for BDF in `lspci -d "*:*:*" | awk '{print $1}'`; do
# skip if it doesn't support ACS
sudo setpci -v -s ${BDF} ECAP_ACS+0x6.w > /dev/null 2>&1
if [ $? -ne 0 ]; then
continue
fi
sudo setpci -v -s ${BDF} ECAP_ACS+0x6.w=0000
done
虚拟机
虚拟机需要 ACS 才能运行,因此禁用 ACS 不是一种选择。为了在虚拟机内部以最大性能运行,需要在网络适配器中启用 ATS。
拓扑检测¶
NCCL 依赖 /sys 来发现 GPU 和网卡的 PCI 拓扑。在虚拟机或容器内运行时,请确保正确挂载 /sys。让 /sys 公开虚拟 PCI 拓扑可能会导致次优性能。
网络问题¶
IP 网络接口¶
NCCL 自动检测要用于节点间通信的网络接口。如果某些接口处于 UP 状态但无法在节点之间通信,则 NCCL 可能会尝试仍然使用它们,因此在初始化函数期间失败甚至挂起。
有关如何指定要使用的接口的信息,请参阅环境变量部分,特别是 NCCL_SOCKET_IFNAME
环境变量。
IP 端口¶
NCCL 打开 TCP 端口以将进程连接在一起并交换连接信息。要限制 NCCL 使用的端口范围,可以设置 Linux 内核的 net.ipv4.ip_local_port_range
属性。
此示例显示如何将 NCCL 端口限制为 50000-51000
echo 50000 51000 > /proc/sys/net/ipv4/ip_local_port_range
或者要使其永久生效,请在 /etc/sysctl.conf 中添加一行
echo "net.ipv4.ip_local_port_range = 50000 51000" >> /etc/sysctl.conf
限制端口范围对于在防火墙中打开相应的范围可能很有用,例如在 Google Cloud 上
gcloud compute --project=myproject firewall-rules create ncclnet0-ingress --direction=INGRESS --priority=1 --network=ncclnet --action=ALLOW --rules=tcp:50000-51000,22,1024-1039 --destination-ranges=0.0.0.0/0 --target-tags=ncclnet
InfiniBand¶
在 InfiniBand 上运行 NCCL 之前,运行低级 InfiniBand 测试(特别是 ib_write_bw 测试)可以帮助验证节点是否能够正常通信。
InfiniBand 常见的一个问题是库无法注册足够的固定内存。在这种情况下,您可能会看到类似以下的错误
NCCL WARN Call to ibv_create_qp failed
或
NCCL WARN Call to ibv_reg_mr failed
解决方案是删除用户对注册固定内存的限制。可以通过添加以下行来完成
* soft memlock unlimited
* hard memlock unlimited
到 /etc/security/limits.conf
配置文件或 Linux 发行版上的等效文件。
基于融合以太网的 RDMA (RoCE)¶
在 RoCE 上运行 NCCL 之前,运行低级 RDMA 测试(特别是 ib_write_bw
测试)可以帮助验证节点是否能够正常通信。
RoCE 常见的一个问题是为 RoCE v2 NIC 选择了不正确的 GID 索引。这可能会导致以下错误
NCCL WARN Call to ibv_modify_qp failed with error Invalid argument
在 NCCL 2.21 及更高版本中,GID 索引是动态选择的,但在早期版本中,用户需要运行
show_gids
然后将 NCCL_IB_GID_INDEX
设置为 RoCE v2 VER GID 的 GID INDEX。对于 NCCL 2.21 及更高版本,不应设置此环境变量。
用户可能还需要在使用基于 RoCE 的网络时设置 NCCL_IB_TC
。有关应设置为的值,请参阅您的供应商文档。