AI Infra Interviews logo
Networking, Interconnects & Storage / 06
medium★ EssentialNewCrusoeLambdaCoreWeave

A 64-node job's all-reduce runs at a third of the expected bandwidth. Walk me through finding the cause.

Find the scale at which it breaks before looking at any node, because the scale tells you which layer to open. The commands in order, the number each should return on a healthy fabric, and the four causes that this measurement sequence separates without guessing.

Updated Sep 2026 · Grounded in real AI infrastructure interview loops and written to a senior-engineer editorial bar, with every number worked and every diagram hand-built.

TL;DR: Do not start at a node. Start by finding the scale at which the bandwidth falls, because that single fact eliminates most of the search space. Run all_reduce_perf within one node, then across two, four, eight and sixty-four, and compare the bus bandwidth at each step against the rated link speed. A drop that is already present inside one node points at NVLink or at GPUDirect being off. A drop that first appears at two nodes points at the network path for one pair, which pairwise ib_write_bw then localizes to a link or a NIC. A drop that appears only at large scale, with every pair healthy, points at congestion or at a ring that crosses the fabric badly, and the evidence for those is switch counters and the ring layout printed at startup. The four causes are distinguished by measurement rather than by inspection, and the whole sequence takes about fifteen minutes.

How to approach it

Say the localization principle first: measure at increasing scale until the number breaks, because the breaking point names the layer. Then give the commands in that order with the healthy value for each, since a check without an expected number is not a check. Then map each outcome to its cause and its fix. Close with the one cause that hides from this sequence, which is intermittency.

A strong answer

A typical situation: a job that ran fine last week now reports a third of the expected all-reduce bandwidth. The team starts reading NCCL environment variables and trying settings, which changes the number slightly in both directions and produces no diagnosis. Nothing has been measured at a scale small enough to isolate anything.

The sequence, with the number each step should return:

0. establish the target
   one 400 Gb/s NIC per GPU = 50 GB/s. A healthy multi-node all-reduce reports bus bandwidth
   near that per GPU. Read the bus bandwidth column, not algorithm bandwidth: bus bandwidth
   already accounts for the 2(N-1)/N factor and is what compares against line rate.

1. inside one node, 8 GPUs
   ./all_reduce_perf -b 8 -e 8G -f 2 -g 8
   healthy: bus bandwidth well above a single NIC's rate, because this stays on NVLink
   if slow here: the problem is not the network. Check nvidia-smi nvlink -s for inactive links
   and nvidia-smi topo -m for an unexpected layout.

2. two nodes, 16 GPUs
   healthy: close to 50 GB/s per GPU
   if this is the first drop: one pair's network path is bad. Go to step 3.

3. pairwise point to point
   ib_write_bw between the two nodes, per NIC pair, message size 1 MB and above
   healthy: about 45 to 48 GB/s on a 400 Gb/s port, and 1.5 to 2 us on ib_write_lat
   a single pair well below that names a NIC, a cable or a switch port.

4. four, eight, sixty-four nodes
   healthy: bus bandwidth stays flat as scale grows. A ring's per-rank traffic does not grow
   with N, so a fabric with enough bisection bandwidth holds the number.
   if the drop appears only here: congestion or ring layout, which is step 5.

5. the ring and the counters
   NCCL_DEBUG=INFO shows the rings built and whether GDRDMA is in use
   switch port counters: pause frames, ECN marks, discards, symbol errors, link flaps
   healthy: pause and discard counters flat during the run

sanity: the whole sequence is five measurements and about fifteen minutes, against a job
        losing a third of its throughput every hour it runs. Measure before touching a
        setting, because every variable you change without a diagnosis has to be unchanged
        later by someone who will not know why it was set

Debugging a Slow All-Reduce is the concept page; this is the drill with the numbers attached.

rendering diagram…

The four causes, and what each looks like:

CauseSignatureFix
GPUDirect disabledRoughly half the expected bandwidth from two nodes upward, GDRDMA absent in the NCCL log, higher CPU useLoad the peer-memory module; check the GPU and NIC are on the same PCIe root; set NCCL_NET_GDR_LEVEL
One bad link or portThe drop appears at the first scale that includes that node, and ib_write_bw names the pairReplace the cable or transceiver; drain the node; check symbol error counters on the port
Wrong NIC per GPUAll pairs healthy, bandwidth still low, rings in the log hop between railsSet NCCL_IB_HCA to bind each GPU to its nearest interface, or supply a topology file
CongestionOnly at scale, pause frame or ECN counters climbing on switch ports during the runFabric configuration, or the fabric is oversubscribed for this traffic pattern

The one cause this sequence hides is intermittency. A link that flaps once an hour passes every check you run and destroys a long job, because a collective stalls until a timeout fires. That needs a different instrument: link counters sampled continuously and compared over days, plus the NCCL flight recorder enabled so that when a job does hang there is a record of which rank never arrived. Stragglers and Hangs covers that path, and the tell that sends you there is a job whose bandwidth is fine when measured and whose wall-clock progress is not.

The reversal condition: this whole procedure assumes the collective is actually slower than the fabric allows. Before running any of it, check that the expectation is right. A job doing an all-reduce of small tensors many times per step is latency-bound rather than bandwidth-bound, and its bus bandwidth will read low for a reason no cable replacement will fix. Compare the message size against the crossover where the ring's latency term stops dominating, and if the messages are small the answer is bucketing them, not repairing the fabric.

What interviewers probe next

  • "Why bus bandwidth rather than algorithm bandwidth?" Algorithm bandwidth is message size over time and is not comparable across collectives or rank counts. Bus bandwidth applies the factor each collective actually moves, so it compares against line rate directly.
  • "What does it mean if bandwidth falls as you add nodes?" Either the fabric is oversubscribed at that scale or the rings begin crossing the spine. A well-provisioned fat tree holds the number flat, since per-rank ring traffic does not grow with N.
  • "How do you tell a bad cable from a bad NIC?" Move the cable to a known-good port and re-measure. Symbol error counters on the switch port also localize it, since a failing transceiver raises them on one side.
  • "What if only one job is slow and others are fine?" That points at placement and rank mapping rather than at hardware, since the hardware is serving the other jobs.

Common mistakes

  • Changing environment variables before measuring at any scale, which produces movement without a diagnosis.
  • Reading algorithm bandwidth and comparing it against line rate.
  • Testing on two nodes only, which never creates the congestion that appears at 64.
  • Concluding the fabric is broken when the job's messages are too small to be bandwidth-bound at all.

Key takeaways

  • Localize by scale first: 1, 2, 4, 8, 64 nodes, and the breaking point names the layer.
  • Healthy numbers: about 45 to 48 GB/s on ib_write_bw for a 400 Gb/s port, bus bandwidth near 50 GB/s per GPU across nodes, and flat as scale grows.
  • Four causes with distinct signatures: GPUDirect off, one bad link, wrong NIC per GPU, congestion.
  • Intermittent faults pass every check; they need continuous counters and the NCCL flight recorder instead.
That one was free — and so are 10 answers per topic without an account. Signing in doubles that to 20, opens the Plus lessons in the courses, and remembers which topics you keep getting wrong.no card · Google sign-in · nothing to cancel
HOW DID IT GO?
0
READING SIGNED OUT

Signing in doubles your free answers, from 10 to 20 per topic, and the site starts remembering you: mastery per topic, bookmarks, and a next-focus recommendation. Free, no card.

Sign in free

The concepts behind this question

Ranked by how closely each one overlaps this question's topic, so the first card is the thing to read if the answer above moved too fast.

Foundational
🔌 Networking & Storage
Debugging a Slow All-ReduceA training job reports its all-reduce at a third of what the fabric should deliver, every node passed its health check, and nothing is logged. This page is the isolation order that finds the cause in an hour instead of a day: measure the collective in isolation, split the job until the slow pair or rank appears, then check the specific things that make a link, a node or a placement slow. Most cases end at one NIC, one topology mismatch, or GPUDirect silently off.
Foundational
🔌 Networking & Storage
NCCL and Collective AlgorithmsNCCL is the library every PyTorch collective lands in, and its choice of ring or tree, channel count and protocol decides whether an all-reduce runs at fabric speed or at a third of it. Knowing what NCCL_DEBUG=INFO prints, and which environment variable changes which decision, is the difference between tuning a cluster and guessing at it.
Core
🔌 Networking & StorageSign in
RDMA, InfiniBand and RoCEv2Training across nodes moves hundreds of gigabytes per step, and a CPU-driven TCP stack cannot feed a 400 Gb/s link. RDMA lets a NIC write straight into a remote GPU's memory with no kernel and no copies, and it runs over two fabrics: InfiniBand, which is lossless by design, and RoCEv2, which is Ethernet made lossless by configuration. The choice is operational as much as technical, and the numbers that decide it are per-GPU bandwidth, the collective's volume, and who will debug a pause storm at 3 a.m.
Advanced
🔌 Networking & Storage🔒 Premium
GPUDirect RDMA and GPUDirect StorageBy default a byte leaving a GPU for the network or the disk makes a detour through host memory, crossing PCIe twice and costing a CPU copy. GPUDirect RDMA lets the NIC read and write GPU memory directly, and GPUDirect Storage does the same for NVMe. The win is not raw bandwidth (PCIe is the ceiling either way) but the halving of PCIe traffic and the removal of the host as a bottleneck, which is what makes collectives run at NIC rate and checkpoints run at drive rate. When it is silently off, everything still works, at half speed.
UP NEXT ON YOUR JOURNEY
FEDITOR'S NOTE

Scored on measuring at increasing scale to localize before inspecting, on knowing the healthy numbers for each check, and on separating a bad link from a bad mapping from a disabled GPUDirect path.

DISCUSSION · 0

No comments yet — be the first to share your approach.