Run CVS InfiniBand bandwidth and latency IB tests#
2026-10-28
13 min read time
InfiniBand (IB Perf) tests measure raw bandwidth and latency across the cluster fabric with the perftest tools (ib_write_bw, ib_read_bw, ib_send_bw, ib_write_lat, ib_read_lat, and ib_send_lat). Run IB Perf after burn-in passes and before RCCL tests to validate that the interconnect delivers expected throughput.
The same tools run on RoCE. The shipped config expects GID type RoCE v2.
Prerequisites#
A cluster file with at least two nodes. One node cannot form a server/client pair.
SSH key access from the machine where you run
cvs, as in your cluster file.A ROCm install on every node. Set
rocm_dirin the config below, or""to auto-detect.amd-smion every node, onPATHor at/opt/rocm/bin. GPU discovery uses it.install_system_packagesnever installs it, and the install suite fails on a node without it.On every node:
numactl,libibverbs,librdmacm,lshw, and therdmacommand. The install suite canapt installthe perftest build and runtime packages,lshw, andiproute2(forrdma) wheninstall_system_packagesisTrue. That install is skipped inside a SPUR or Slurm job step.On the head node, when
install_perf_packageisTrue:git,build-essential, the autotools build chain,pkg-config, thelibibverbs,librdmacm,libibumad, andlibpcidevelopment packages (the setinstall_system_packagesinstalls), and access tohttps://github.com/linux-rdma/perftest.Each backend NIC has a network interface (on InfiniBand, an IPoIB interface). Ports without one are not used.
Each client reaches its server at the address the cluster file uses for that node, on TCP ports
port_noup toport_noplus the GPU count minus one.install_diron a filesystem shared by every node at the same path, such as a shared home. The install suite builds perftest on the head node only, and every node runs<install_dir>/perftest/bin/<tool>.Passwordless sudo on the nodes if you use AFM vPOD discovery (
sudo -n afmctl) or want the dmesg scan (sudo dmesg). Without sudo, the dmesg scan is skipped and AFM pairing stops.
Set up config#
Copy the IB performance configuration file:
cvs config copy ibperf/ibperf_config.json --output ~/cvs_workspace/ibperf/ibperf_config.json
Edit
~/cvs_workspace/ibperf/ibperf_config.json:Replace
rocm_dir. The value<changeme>stops the run during placeholder resolution, before auto-detect. Set a real path such as/opt/rocm, or""to auto-detect/opt/rocm/core-*and then/opt/rocm.Set
install_dirif/home/{user-id}/is not the shared directory you want.{user-id}becomes the cluster fileusername(then$USER, thenroot).Set
ib_bw_test_listandib_lat_test_listto the perftest binaries you want. These lists are the cases that run. See InfiniBand (IB Perf) test configuration file for Cluster Validation Suite (CVS).Set
gid_indexfor your NICs, orautoto select the lowest index usable on every NIC. The shipped3is checked againstgid_typebefore perftest starts.Replace the
expected_resultsnumbers for your fabric before you treat a pass as a performance gate. The shipped numbers apply only toib_write_bwat 8192 bytes.
No other shipped field contains
<changeme>. A remaining<changeme>exits at startup withUnresolved placeholder found in test config.
For the field reference, pairing, and pass/fail rules, see InfiniBand (IB Perf) test configuration file for Cluster Validation Suite (CVS).
Topology#
Nodes are paired as server and client. With the shipped pairing_mode of sequential, pair 1 is the first and second node in the cluster file, pair 2 is the third and fourth, and so on. The first node of each pair is the server. An odd last node is left out and logged. It does not by itself fail the test.
Each GPU runs its own perftest process on its local NIC. The server starts first and each client connects after about 5 seconds. Ports start at port_no and increase by one per GPU.
Bandwidth runs are bidirectional (-b) and pass -D <duration>, -q <qp>, -s <bytes>, and --report_gbits. The reported Gbps is the sum of both directions, so set expected_results against bidirectional numbers. Latency runs pass -s <bytes> and ignore duration and qp_count_list.
To pair across or within vPODs, set pairing_mode to inter_vpod or intra_vpod in the same config. See the vPOD-aware pairing reference for vpod_source, afmctl_path, and the sudo it needs.
Run tests#
List the cases for the file you edited. Pass --config_file; without it, cvs list shows the built-in default lists, not the shipped file’s (see InfiniBand (IB Perf) test configuration file for Cluster Validation Suite (CVS)).
cvs list ib_perf_bw_test \
--cluster_file ~/cvs_workspace/cluster.json \
--config_file ~/cvs_workspace/ibperf/ibperf_config.json
For the shipped lists, collection looks like this (cvs list sorts names; the suite runs test_launch_containers, the bandwidth cases, the latency cases, the two chart tests, then test_teardown_containers). The two container steps skip on bare metal:
Available tests in ib_perf_bw_test:
--------------------------------------------------------------------------------
• test_build_ib_bw_perf_chart
• test_build_ib_lat_perf_chart
• test_ib_bw_perf[ib_send_bw]
• test_ib_bw_perf[ib_write_bw]
• test_ib_lat_perf[ib_read_lat]
• test_ib_lat_perf[ib_send_lat]
• test_ib_lat_perf[ib_write_lat]
• test_launch_containers
• test_teardown_containers
Total: 9 tests
test_ib_bw_perf[ib_write_bw] is one pytest node id. The brackets are part of the id. Quote them so the shell does not treat [ as a glob.
Install perftest once, then run the suite. Both commands use the config you edited:
cvs run install_ibperf_tools \
--cluster_file ~/cvs_workspace/cluster.json \
--config_file ~/cvs_workspace/ibperf/ibperf_config.json \
--workspace ~/cvs_workspace \
--capture=tee-sys -vvv
cvs run ib_perf_bw_test \
--cluster_file ~/cvs_workspace/cluster.json \
--config_file ~/cvs_workspace/ibperf/ibperf_config.json \
--workspace ~/cvs_workspace \
--capture=tee-sys -vvv
Set install_perf_package to False when <install_dir>/perftest/bin already contains the ROCm build you want. The install test then logs Skipping perftest installation. With True and an existing <install_dir>/perftest checkout, git clone fails without failing the test, and the existing checkout is rebuilt as is. Delete <install_dir>/perftest first to build a fresh copy.
Run one bandwidth case and its spreadsheet in the same command. The chart test reads measurements stored in that process. A chart test run in a separate cvs run has no measurements to chart:
cvs run ib_perf_bw_test \
'test_ib_bw_perf[ib_write_bw]' \
test_build_ib_bw_perf_chart \
--cluster_file ~/cvs_workspace/cluster.json \
--config_file ~/cvs_workspace/ibperf/ibperf_config.json \
--workspace ~/cvs_workspace \
--capture=tee-sys -vvv
A latency case is 'test_ib_lat_perf[ib_read_lat]' plus test_build_ib_lat_perf_chart. An unknown name, a duplicate, or a non-list value fails collection with the ValueError from configured_bw_tests or configured_lat_tests. An empty list collects no cases for that side. The chart tests are still collected. On the container backend, also select test_launch_containers; it attaches to a persistent container that is already running.
Run on managed compute#
Follow Run Cluster Validation Suite (CVS) on managed compute to run IB Perf on managed compute. Inside a job step, install_system_packages does not run apt; install the perftest packages in the node image beforehand.
Run in containers#
Follow Run Cluster Validation Suite (CVS) test suites with a per-host Docker container backend and set "orchestrator": "container" in the cluster file. The install and test suites start the container on every node in their first step, or attach to the one already running, and run the perftest build, perftest, and the GPU and NIC checks inside it. With persistent the container keeps running after the test suite; remove it yourself. The dmesg scan and AFM vPOD discovery stay on the host, so the dmesg scan needs passwordless sudo on the hosts, as on baremetal.
IB Perf needs these container settings:
container.lifetimepersistent. The install and test suites are separate runs, and aper_runcontainer is removed between them with anything installed in it.install_diron a volume incontainer.runtime.args.volumesthat every node shares, mounted at the same path in the container. The build runs in the head node’s container and every node runs the result.An image with ROCm at
rocm_dirandamd-smi, even wheninstall_system_packagesisTrue. The install suite never installs either, and it fails on a node withoutamd-smi. The image also needslshw,rdma(fromiproute2),numactl,libibverbs, andlibrdmacm, unlessinstall_system_packagesisTrueand the image hassudo.install_ibperf_toolsfails when any of them is still missing, with or without apt.
What a pass produces#
cvs run writes the pytest HTML report, log, and zip bundle described in Pytest HTML report and bundle, and includes the IB Perf Run Deck. A GPU under a configured threshold fails the pytest test.
The chart tests write two workbooks in the directory where you started cvs, not in the run directory, and they are not in the zip:
ib_bw_pps_perf.xlsx: one sheet per bandwidth test and QP count, with bandwidth in Gbps, the perftest message rate, and a cluster-average chart.ib_lat_perf.xlsx: one sheet per latency test, with min, max, average, stdev, and 99th percentile in microseconds.
Each node keeps perftest output in /tmp/ib_perf_<n>_logs, one file per GPU instance numbered from 0 in card order. Every bandwidth run (message size and QP count) and every latency run (message size) deletes and rewrites these files, so after the suite they hold only the last run. They are not copied into the run directory.
Troubleshooting#
Search the pytest log for FAIL -. The test then ends with Following FAILURES seen.
What you see |
What it means |
|---|---|
|
A |
|
The install suite saw fewer than two nodes in the cluster file. |
|
Pairing produced no server/client pair. Check |
|
AFM mode could not run |
|
|
|
|
|
The in-tree binary |
|
|
|
That GPU has no active backend NIC in its PCI domain. The test stops before perftest. |
|
The two nodes of a pair discovered different card lists, or none. No cards usually means |
|
The binary is missing on that node, does not load with |
|
That perftest process exited non-zero, even if it printed a result. Check that instance’s |
|
The head-node build failed with and without DMA-BUF. The last configure lines follow the message. Check |
|
The configured |
|
|
|
The perftest log has no |
|
No result row for that size. On bandwidth runs, |
|
A GPU instance was under |
|
A GPU instance’s average latency ( |
|
The dmesg scan matched a known error line on that node during the run. |
|
|
No expected result configured ... not gated is informational. That size ran and was not compared to a threshold.
Kernel log (dmesg) scan#
After each bandwidth and latency run, the suite reads dmesg on every node from the minute the run started and fails the test if it finds a known error pattern. The end time is not applied (till_end_flag=True), so the scan continues through the kernel log collected at the end of that message size. The log is parsed with AMD node-scraper (the amd-node-scraper package installed with CVS), extended with the CVS error patterns.
If any node lacks passwordless sudo, the scan is skipped and the log says SKIPPING the dmesg error check: no passwordless sudo to read dmesg on one or more nodes. The bandwidth and latency numbers can still pass.