跳到主要内容

故障排除

确保您熟悉以下已知问题和有用的调试策略。

错误

MCCL 调用可能会返回各种返回码。确保返回码始终等于 mcclSuccess。如果任何调用失败并返回与 mcclSuccess 不同的值,将 MCCL_DEBUG 设置为 "WARN" 将使 MCCL 在返回错误之前打印一个明确的警告消息。

错误被分为不同的类别。

  • mcclUnhandledmusaError 和 mcclSystemError 表示对外部库的调用失败。
  • mcclInvalidArgument 和 mcclInvalidUsage 表示使用 MCCL 的应用程序中存在编程错误。

在任何情况下,请参阅 MCCL 警告消息以了解如何解决问题。

RAS

从 2.24 版本开始,MCCL 包括一个可靠性、可用性和服务性(RAS)子系统,以帮助诊断和调试崩溃和挂起。

GPU Direct

MCCL 严重依赖 GPU Direct 进行 GPU 间通信。这指的是 GPU 能够直接与另一个设备(如另一个 GPU 或网卡)使用直接点对点 PCI 消息进行通信的能力。

直接点对点 PCI 消息可能因各种原因失败或表现不佳,例如缺少组件、虚拟机或容器的配置错误,或某些 BIOS 设置。

GPU 到 GPU 通信

为确保 GPU 到 GPU 通信正常工作,请查找 MUSA 示例中的 p2pBandwidthLatencyTesthttps://github.com/mthreads/musa-samples

cd musa-samples/Samples/5_Domain_Specific/p2pBandwidthLatencyTest
make
./p2pBandwidthLatencyTest

测试应该能够顺利完成,并报告 GPU 之间的良好性能。

另一个检查 GPU 到 GPU 性能的工具叫做 nvbandwidth。这可以从以下代码和说明中下载并构建: https://github.com/mthreads/mtbandwidth

GPU 到 NIC 通信

GPU 也可以使用 GPU Direct RDMA (GDRDMA) 直接与网卡通信。这需要有兼容的网卡和驱动程序,以及加载一个额外的内核模块称为 mthreads-peermemmthreads-peermem 模块现在随 MUSA 驱动程序提供,但必须在每个节点启动时加载:

sudo modprobe mthreads-peermem

GDRDMA 也可以通过使用最新 Linux 内核的 DMA-BUF 特性结合开源 mthreads GPU 驱动程序来启用。在这种情况下,MCCL 将自动检测并启用 DMA-BUF,因此不需要 mthreads-peermem 模块。

PCI 访问控制服务 (ACS)

裸机系统

IO 虚拟化(也称为 VT-d 或 IOMMU)可能通过将所有 PCI 点对点流量重定向到 CPU 根复合体来干扰 GPU Direct,导致性能显著降低甚至挂起。您可以通过运行以下命令来检查 PCI 桥是否启用了 ACS:

sudo lspci -vvv | grep ACSCtl

如果行显示 "SrcValid+",则可能启用了 ACS。查看 lspci 的完整输出,可以检查 PCI 桥是否启用了 ACS。

sudo lspci -vvv

如果 PCI 开关启用了 ACS,则需要禁用它。在某些系统上,这可以通过 BIOS 禁用 IO 虚拟化或 VT-d 来完成。对于 Broadcom PLX 设备,可以从 OS 完成,但需要在每次重启后再次完成。

使用以下命令找到 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
# 如果不支持 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。

拓扑检测

MCCL 依赖于 /sys 来发现 GPU 和网卡的 PCI 拓扑。在虚拟机或容器内运行时,请确保 /sys 正确挂载。让 /sys 暴露虚拟 PCI 拓扑可能导致性能不佳。

共享内存

为了在进程之间甚至在进程的线程之间进行通信,MCCL 在 /dev/shm 中创建共享内存段。操作系统对这些资源的限制可能需要相应增加。请参阅您的系统文档以获取详细信息。

如果共享内存不足,MCCL 将无法初始化。使用 MCCL_DEBUG=WARN 运行将显示类似以下的消息:

MCCL WARN Error: failed to extend /dev/shm/mccl-03v824 to 4194660 bytes

Docker

特别是,Docker 容器默认限制共享和固定内存资源。在容器内使用 MCCL 时,请确保调整容器内的共享内存大小,例如,通过向 docker 启动命令行添加以下参数:

--shm-size=1g --ulimit memlock=-1

Systemd

当使用 mpirun 或 SLURM 运行作业时,systemd 可能会在检测到相应用户未登录时删除共享内存中的文件,试图清理旧的临时文件。这可能导致 MCCL 在初始化期间崩溃,并出现类似以下的错误:

MCCL WARN unlink shared memory /dev/shm/mccl-d5rTd0 failed, error: No such file or directory

鉴于 mpirun 和 SLURM 作业可以在节点上运行而用户不被 systemd 视为已登录,系统管理员需要禁用该清理机制,这可以通过 SLURM 尾声脚本来完成。为此,需要在 /etc/systemd/logind.conf 中设置以下行:

RemoveIPC=no

更新后,应使用以下命令重启守护进程:

sudo systemctl restart systemd-logind

muMem主机内存分配机制

从MCCL 2.23版本开始,MCCL支持采用muMem主机内存分配(muMem host allocations)作为替代的共享内存机制。自MCCL 2.24起,若满足MUSA驱动≥12.6且MUSA运行时≥12.2,该功能将默认启用,并优先替代传统的/dev/shm机制。

然而,muMem主机内存分配依赖于正确配置且可用的NUMA(非统一内存访问)支持,而某些虚拟机(VM)和容器化环境可能无法提供这一支持。例如,Docker默认禁用NUMA支持(可通过--cap-add SYS_NICE参数启用)。

从MCCL 2.26.5版本开始,若检测到muMem主机内存分配不可用,MCCL会自动回退至/dev/shm方案。对于更早的版本,需手动设置环境变量MCCL_muMem_HOST_ENABLE=0以实现相同效果。

我们仍建议配置底层系统以确保muMem主机内存分配可用,因为该机制在通信器(communicator)异常终止时能提供更高的可靠性。

网络问题

IP 网络接口

MCCL 自动检测用于节点间通信的网络接口。如果某些接口处于 UP 状态但无法在节点间通信,MCCL 仍可能尝试使用它们,因此在 init 函数期间或甚至挂起时失败。

有关如何指定要使用的接口的信息,请参见环境变量部分,特别是 MCCL_SOCKET_IFNAME 环境变量。

IP 端口

MCCL 打开 TCP 端口以连接进程并交换连接信息。要限制 MCCL 使用的端口范围,可以设置 Linux 内核的 net.ipv4.ip_local_port_range 属性。

此示例显示如何将 MCCL 端口限制为 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 mcclnet0-ingress --direction=INGRESS --priority=1 --network=mcclnet --action=ALLOW --rules=tcp:50000-51000,22,1024-1039 --destination-ranges=0.0.0.0/0 --target-tags=mcclnet

InfiniBand

在 InfiniBand 上运行 MCCL 之前,运行低级别的 InfiniBand 测试(特别是 ib_write_bw 测试)可以帮助验证节点是否能够正常通信。

InfiniBand 的常见问题是库无法注册足够的固定内存。在这种情况下,您可能会看到类似以下的错误:

MCCL WARN Call to ibv_create_qp failed

MCCL WARN Call to ibv_reg_mr failed

解决方案是取消对注册固定内存的用户限制。这可以通过向 /etc/security/limits.conf 配置文件或您的 Linux 发行版中的等效文件添加以下行来完成:

* soft memlock unlimited
* hard memlock unlimited

通过聚合以太网 (RoCE) 的 RDMA

在 RoCE 上运行 MCCL 之前,运行低级别的 RDMA 测试(特别是 ib_write_bw 测试)可以帮助验证节点是否能够正常通信。

RoCE 的常见问题是为 RoCE v2 NIC 选择了错误的 GID 索引。这可能导致以下错误:

MCCL WARN Call to ibv_modify_qp failed with error Invalid argument

使用 MCCL 2.21 及更高版本,GID 索引是动态选择的,但在早期版本中,用户需要运行:

show_gids

然后设置 MCCL_IB_GID_INDEX 为 RoCE v2 VER GID 的 GID 索引。使用 MCCL 2.21 及更高版本时,不应设置此环境变量。

使用基于 RoCE 的网络时,用户可能还需要设置 MCCL_IB_TC。有关应设置的值,请参阅供应商的文档。