单机 GPU 通信瓶颈排查

多卡 GPU 拓扑排查与带宽实测手册

记录一次完整的排查过程:从 nvidia-smi topo -m 读拓扑,到发现 PCIe ACS 拖慢 NCCL 通信,再到写 systemd service 修复。机器:8x NVIDIA RTX PRO 6000 Blackwell Server Edition,AMD EPYC 双路。

GPU 拓扑

nvidia-smi topo -m

从近到远:NVLink > PIX > PXB > PHB > NODE > SYS

类型 含义
NV# 绑定 # 条 NVLink
PIX 最多一级 PCIe 桥
PXB 多级 PCIe 桥,不经过 Host Bridge
PHB 经过一个 PCIe Host Bridge(同一个 root complex)
NODE 同 NUMA 节点内,但要跨多个 Host Bridge
SYS 跨 NUMA 节点,走 QPI/UPI

判断有没有 PCIe Switch:矩阵里出现 PXB/PIX 才说明设备共享了某个 Switch;
只有 PHB/NODE/SYS 说明是直连 CPU root port,没有 Switch。

P2P 带宽/延迟

git clone https://github.com/NVIDIA/cuda-samples.git
cd cuda-samples/cpp/5_Domain_Specific/p2pBandwidthLatencyTest
nvcc -I../../../Common p2pBandwidthLatencyTest.cu -o p2pBandwidthLatencyTest
./p2pBandwidthLatencyTest

NCCL all-reduce 实测

git clone https://github.com/NVIDIA/nccl-tests.git
cd nccl-tests
make MPI=0 -j"$(nproc)"

# TP=4,只用一个 NUMA 节点内的卡
CUDA_VISIBLE_DEVICES=0,1,2,3 ./build/all_reduce_perf -b 8M -e 512M -f 2 -g 4

# TP=8,跨 NUMA
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 ./build/all_reduce_perf -b 8M -e 512M -f 2 -g 8

看输出最后一行 Avg bus bandwidth

排查用得上的调试开关:

NCCL_DEBUG=INFO ./build/all_reduce_perf -b 256M -e 256M -g 4 2>&1 \
  | grep -Ei "NCCL INFO (NET|Channel|P2P|Trees|Ring|Graph|Topology|GDR|comm )"

关键看 Channel XX : i[dev] -> j[dev] via XXX 这一行的传输方式:

  • via P2P/... = 走的是 GPU 直连
  • via SHM/... = 退化成主机内存中转,带宽会差一个数量级以上,八成是 ACS 的锅(见下)

检查 NCCL 走 SHM 而不是 P2P

症状:p2pBandwidthLatencyTest 测出来的原生 CUDA P2P 带宽正常(几十 GB/s),
但 NCCL all_reduce_perfbusbw 只有个位数 GB/s,且日志显示 via SHM/direct/direct

排查:

# 每张 GPU 是不是各自单独一个 IOMMU group(本该同一 Host Bridge 下的卡合并成一组)
for d in /sys/kernel/iommu_groups/*/devices/*; do
  bdf=$(basename "$d")
  vendor=$(cat "$d/vendor" 2>/dev/null)
  [ "$vendor" = "0x10de" ] && echo "GPU $bdf -> group $(echo "$d" | grep -oP 'iommu_groups/\K[0-9]+')"
done

如果 8 张卡是 8 个完全独立的 group,基本可以确定是 PCIe ACS(Access Control
Services) 被打开,把所有 P2P 流量都重定向去了 root complex 做隔离校验,
NCCL 检测到之后主动放弃 P2P 传输,退化用共享内存中转。

开机清除 ACS

sudoedit /usr/local/sbin/disable-pcie-acs.sh
#!/bin/bash
# Disable PCIe ACS on all PCI bridges so GPU peer-to-peer DMA is not
# redirected through the root complex.
#
# This is a runtime PCI config space write, not a BIOS setting - it resets
# on every reboot, so it must run at boot before any GPU workload starts
# (see the accompanying disable-pcie-acs.service).
set -euo pipefail

for bdf in $(lspci -D -d '::0604' | awk '{print $1}'); do
    if setpci -s "$bdf" ECAP_ACS+0x6.w >/dev/null 2>&1; then
        setpci -s "$bdf" ECAP_ACS+0x6.w=0000
        logger -t disable-pcie-acs "cleared ACS control on $bdf"
    fi
done
sudoedit /etc/systemd/system/disable-pcie-acs.service
[Unit]
Description=Disable PCIe ACS on all bridges (GPU P2P optimization)
DefaultDependencies=no
Before=sysinit.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/disable-pcie-acs.sh
RemainAfterExit=yes

[Install]
WantedBy=sysinit.target

安装:

sudo chmod +x /usr/local/sbin/disable-pcie-acs.sh
sudo systemctl daemon-reload
sudo systemctl enable disable-pcie-acs.service

验证效果:重启后重复 IOMMU group 检查(应该会合并),再跑一遍 all-reduce 测试对比 busbw

posted @ 2026-07-10 20:40  undefined443  阅读(17)  评论(0)    收藏  举报