Skip to content

Debugging Slow Collectives#

A decision tree for the most common complaint on a GPU cluster: training runs, but much slower than it should. It works from the inside out: first prove one node is healthy, then the RDMA path, then the fabric, then placement. Each check names the layer where the fix lives.

Start by measuring. Run all_reduce_perf from nccl-tests and compare its bus bandwidth (busbw) with what the hardware should deliver. For example, a 400G NIC carries about 50 GB/s per direction, and a healthy inter-node all-reduce reaches a large fraction of that per GPU.

The decision tree#

flowchart TD
    A([busbw well below expected]) --> B{Slow on a<br/>single node too?}
    B -- Yes --> C[L8: check NVLink and P2P<br/>nvidia-smi topo -m<br/>nvidia-smi nvlink -s]
    B -- No, only multi-node --> D{NCCL_DEBUG=INFO:<br/>NET/IB or NET/Socket?}
    D -- NET/Socket --> E[L6 + control plane:<br/>RDMA device not in pod,<br/>IPC_LOCK missing,<br/>NCCL_IB_HCA wrong]
    D -- NET/IB --> F{Log shows<br/>GDRDMA?}
    F -- No --> G[L6/L8: GPUDirect off<br/>nvidia-peermem<br/>or dma-buf,<br/>ACS / IOMMU settings]
    F -- Yes --> H{Each GPU paired<br/>with its own NIC?<br/>PIX or PXB in topo}
    H -- No, SYS or NODE --> I[L8 + control plane:<br/>wrong NIC mapping,<br/>Topology Manager policy]
    H -- Yes --> J{One node or link<br/>slower than the rest?}
    J -- Yes --> K[L7: bad link or port<br/>ib_write_bw between pairs,<br/>port error counters]
    J -- No --> L{RoCE: pause frames<br/>or ECN marks climbing?}
    L -- Yes --> M[L7: congestion config<br/>PFC, ECN, DCQCN tuning]
    L -- No --> N[Control plane + L3:<br/>rank placement,<br/>TP crossing nodes,<br/>rails crossing spine]

The checks, with commands#

# Check How Healthy result
1 Single-node bandwidth all_reduce_perf -b 8 -e 8G -f 2 -g 8 on one node Close to NVLink bandwidth for the GPU generation
2 NVLink topology nvidia-smi topo -m NV# between every pair of GPUs
3 NVLink errors nvidia-smi nvlink -s and -e All links up, error counters not growing
4 RDMA in use NCCL_DEBUG=INFO, look for NET/IB : Using [0]mlx5_... NET/IB, never NET/Socket for GPU traffic
5 GPUDirect RDMA Same log, look for via NET/IB/<n>/GDRDMA GDRDMA on inter-node channels
6 GPU-NIC affinity nvidia-smi topo -m, GPU rows vs NIC columns Each GPU has PIX or PXB to its NIC, not SYS
7 Point-to-point links ib_write_bw between each pair of nodes Every pair close to line rate; no outlier
8 Port errors perfquery (InfiniBand) or ethtool -S (RoCE) Symbol, link-down and discard counters flat
9 Congestion (RoCE) ethtool -S: pause and ECN/CNP counters Low and stable under load, no pause storms
10 Placement Rank-to-node map against the fabric topology TP inside a node; DP groups on the same rail

Why the order matters#

The checks run from the inside out because each one assumes the ones before it passed. There is no point tuning ECN (check 9) while NCCL is running over TCP (check 4). The two silent failures, TCP fallback and GPUDirect off, are also the most common and the cheapest to find: both show up in the first lines of an NCCL_DEBUG=INFO log.

See from pod spec to data path for how the RDMA device and IPC_LOCK reach the pod, and life of a training step for where each hop sits in a step.