A rank is one process of the training job. Normally there is one per GPU, so for you a rank = one GPU and its NIC: one physical endpoint on the fabric.
| AI-team term | Your translation (H200, rail-optimised) |
|---|---|
| Global rank | One GPU in the job, numbered 0 … N−1 across all nodes |
| Local rank | GPU index inside the node (0-7) |
| World size | Total GPUs in the job (nodes × 8) |
| Communicator | The set of GPUs taking part in a given collective, usually all of them |
| Rank → NIC | Local rank i → GPU i → NIC i → rail i → a port on rail i's leaf |
So rank 13 on 8-GPU nodes is typically node 1, GPU 5, NIC 5, rail-5 leaf, port x. The “typically” matters, because two things can break the clean mapping:
How to pin it down with facts rather than assumptions:
NCCL_DEBUG=INFO), which logs which IB device each rank uses.ibstat on the host.iblinkinfo / ibnetdiscover.That chain turns “rank 13 is slow” into “node X, mlx5_5, leaf Y port Z”, which is the language you troubleshoot in.
| Step | Test | What you've isolated | If low |
|---|---|---|---|
| 1 | All-reduce inside each node (8 GPUs, no IB) | NVLink/GPU, per node | That node's internals. Not the network |
| 2 | All-reduce across all job nodes | Whole set | Continue. If normal, the network is likely not the cause: check compute stragglers, storage, data loading |
| 3 | 2-node tests (pairs on the same leaves) | Node pair | Outlier node found |
| 4 | Per-NIC on the outlier node (NCCL restricted to one NIC, or ib_write_bw per NIC pair) | One rail on one node | NIC, PCIe, optic, cable or leaf port of that rail |
| 5 | Same-leaf pair vs. cross-leaf vs. cross-SU | Switch tier | Uplinks, spine, adaptive routing, congestion |
Then confirm in telemetry for the specific leaf/port you've identified: error counters, BER, speed/width downgrade, congestion counters.
git clone https://github.com/NVIDIA/nccl-tests.git cd nccl-tests make MPI=1 MPI_HOME=/path/to/mpi CUDA_HOME=/usr/local/cuda NCCL_HOME=/path/to/nccl
Binaries land in build/, e.g. build/all_reduce_perf.
One process driving all 8 GPUs:
./build/all_reduce_perf -b 8 -e 8G -f 2 -g 8
-b 8 -e 8G: message sizes from 8 bytes to 8 GB-f 2: double the size each step-g 8: 8 GPUs in this processWith Slurm:
srun -N 2 --ntasks-per-node=8 --gpus-per-node=8 \ -w node01,node02 \ ./build/all_reduce_perf -b 8 -e 8G -f 2 -g 1
With mpirun:
mpirun -np 16 -H node01:8,node02:8 \ -x NCCL_DEBUG=INFO \ ./build/all_reduce_perf -b 8 -e 8G -f 2 -g 1
NCCL_DEBUG=INFO also prints which IB device each rank uses: this gives you the rank → NIC mapping.
Restrict NCCL to a single NIC (here rail 5):
mpirun -np 2 -H node01:1,node02:1 \ -x NCCL_IB_HCA==mlx5_5 \ -x CUDA_VISIBLE_DEVICES=5 \ ./build/all_reduce_perf -b 8 -e 8G -f 2 -g 1
Or test the raw RDMA path without NCCL, NIC to NIC:
# on node02 (server) ib_write_bw -d mlx5_5 --report_gbits # on node01 (client) ib_write_bw -d mlx5_5 --report_gbits node02
Repeat for each rail (mlx5_0 … mlx5_7).
ibstat mlx5_5 # state, rate (expect 400), physical state iblinkinfo | grep -i <node-or-guid> # which leaf and port it lands on
nccl-tests prints one line per message size, with algbw and busbw columns for out-of-place and in-place runs, then an Avg bus bandwidth summary line. Compare the busbw at the largest sizes (and the whole curve) with your baseline for the same node count and topology.
Verify on your system: Slurm may need –mpi=pmix (or similar) depending on how MPI was built. The NCCL_IB_HCA syntax (a leading = for an exact device-name match) and the device names (mlx5_N) depend on your NCCL version and host. Check ibv_devices for the real names.
Limit: nccl-tests need the nodes, so the job must be drained or paused.