InfiniBand (IB Perf) test configuration file for Cluster Validation Suite (CVS)#
2026-10-29
10 min read time
IB Perf measures throughput and latency with perftest. Bandwidth tests report Gbps. Latency tests report microseconds.
The suite reads the ibperf object. The shipped file is input/config_file/ibperf/ibperf_config.json. Keys whose names start with _ (the _comment_* entries in that file) are not settings.
Note
{user-id} is replaced with the cluster file username, then $USER, then root. {user}, {home}, {home-mount-dir}, {node-dir-name}, and {run_dir} are replaced in the same pass.
Any string that still contains <changeme> stops the run with Unresolved placeholder found in test config. That check runs before ROCm auto-detect. The shipped rocm_dir value <changeme> does not auto-detect. Set a path, or "", or omit rocm_dir.
ibperf_config.json
The block below matches the shipped values the suite reads. The file on disk also has _comment_* keys.
{
"ibperf":
{
"install_perf_package": "True",
"install_system_packages": "False",
"install_dir": "/home/{user-id}/",
"rocm_dir": "<changeme>",
"require_dmabuf": "True",
"pairing_mode": "sequential",
"vpod_source": "afm",
"afmctl_path": "afmctl",
"qp_count_list": [ "8", "16" ],
"ib_bw_test_list": [ "ib_write_bw", "ib_send_bw" ],
"ib_lat_test_list": [ "ib_write_lat", "ib_send_lat", "ib_read_lat" ],
"msg_size_list": [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 ],
"gid_index": "3",
"gid_type": "RoCE v2",
"port_no": "1516",
"duration": "10",
"verify_bw": "True",
"expected_results": {
"ib_write_bw": {
"8192": {
"8": "180.0",
"16": "200.0"
}
}
}
}
}
Which tests run#
configured_bw_tests reads ib_bw_test_list. configured_lat_tests reads ib_lat_test_list. Each name becomes one pytest case, test_ib_bw_perf[<name>] or test_ib_lat_perf[<name>].
List value |
What collection does |
|---|---|
Key omitted |
Bandwidth defaults to |
A list of supported names |
Those binaries run, in that order. The shipped file omits |
|
No cases on that side. The chart tests are still collected. |
Unknown name, duplicate, or a non-list |
Collection fails with |
Supported bandwidth names are ib_write_bw, ib_read_bw, and ib_send_bw. Supported latency names are ib_write_lat, ib_read_lat, and ib_send_lat.
Parameters#
Write install_perf_package, install_system_packages, and verify_bw as strings ("True" or "False"). A JSON true or false there stops the run with a TypeError. They are on when the string contains true in any case. require_dmabuf also accepts JSON booleans, and the strings true / 1 / yes / on and false / 0 / no / off. Any other require_dmabuf value is treated as true.
Parameter |
If you omit the key |
What it changes |
|---|---|---|
|
The install test errors (the key is required there) |
|
|
|
Used only when |
|
The perf tests error (the key is required there) |
Directory for the perftest checkout, on storage shared by every node at the same path. Tests run |
|
Auto-detect |
ROCm prefix passed to perftest |
|
True |
Fail before launch if any node’s binary was built without |
|
|
|
|
|
Used only for vPOD modes. |
|
|
|
|
The bandwidth test errors |
Queue-pair counts for bandwidth only. Latency does not pass |
|
The three write/read/send bandwidth tools |
Bandwidth cases. See the table above. |
|
|
Latency cases. See the table above. |
|
The perf tests error |
Message sizes in bytes, passed as perftest |
|
|
GID index passed as perftest |
|
|
Expected sysfs GID type. |
|
The perf tests error |
First TCP port. Each GPU on a node uses the next port. |
|
The bandwidth test errors |
Seconds for perftest |
|
Off (only a value containing |
Apply |
|
Nothing is gated |
Thresholds. Shape and direction are below. |
expected_results.<bw_test>.<msg_size>.<qp_count> is the minimum bandwidth in Gbps for each GPU instance. The test fails if any instance is below it. An equal value passes. Bandwidth runs are bidirectional (perftest -b), so the value is the sum of both directions.
expected_results.<lat_test>.<msg_size> is the maximum average latency in microseconds (perftest t_avg) for each GPU instance. The test fails if any instance is above it. A latency entry must be a number. A QP object under a latency test fails with must be a latency in usec.
JSON keys are strings. The checker stringifies the message size and the QP count from the sweep, so 8192 and "8192" in the sweep match the key "8192".
Message sizes and QP counts in expected_results that are outside msg_size_list and qp_count_list log expected_results.<path> is not covered by msg_size_list/qp_count_list and will not be checked when verify_bw is on. A sweep point with no threshold logs No expected result configured for <test> msg_size=<size>; not gated and does not fail.
The shipped sample gates only ib_write_bw at 8192 bytes for QP counts 8 and 16, at 180.0 Gbps and 200.0 Gbps. configured_bw_tests still runs ib_send_bw, and configured_lat_tests still runs the three latency tests. Those cases are not gated by this sample. Replace the two numbers for your fabric. The checker uses the numbers in the file you pass. It does not keep a second threshold table.
For ib_read_lat, only the client side of each pair has results. An empty server result is skipped. Other latency tests fail a node that returns no rows.
The failure lines are Actual BW <bw> Gbps less than the expected BW <threshold> Gbps and Actual latency <t_avg> us greater than the expected latency <threshold> us, including the node and GPU index.
vPOD-aware pairing#
sequential pairs consecutive nodes in cluster-file order. inter_vpod pairs nodes from different vPODs for scale-out tests. intra_vpod pairs nodes within each vPOD. Nodes left without a partner are excluded and logged. Discovery errors and pairs excluded during the test cause a test failure.
With vpod_source afm, the suite runs sudo -n afmctl show device --json on each node. AFM vPOD identity is (scaleup_fabric.physical_pod.id, scaleup_fabric.virtual_pod.id). Older AFM builds without these IDs fall back to vpod_accelerators, which is unique only within one physical pod. Overlapping accelerator IDs stop discovery and recommend vpod_source cluster_file. The SSH user must have passwordless sudo for afmctl.
For an explicit cluster-file mapping, set vpod_source to cluster_file and label each node:
"node_dict": {
"n1": {"vpod_id": "A"},
"n2": {"vpod_id": "A"},
"n3": {"vpod_id": "B"},
"n4": {"vpod_id": "B"}
}
inter_vpod then forms (n1, n3) and (n2, n4).
GPUs per node#
The number of GPU instances follows GPU discovery. Both nodes of a pair must report the same GPU cards, and all active pairs must use the same card list. A mismatched pair fails and is excluded while eligible pairs continue.
When GPU and backend-NIC PCI domains overlap, each GPU is paired only with an active NIC in its own domain (nearest bus, then nearest device). A GPU with no eligible NIC is left unmapped. The bandwidth or latency test then fails before perftest with No active backend RDMA NIC in the PCI domain of <card>. If a domain has more GPUs than NICs, a NIC can be shared. That is logged (shares NIC) and the test still launches.
Perftest command lines and the in-memory results live for one
cvs runprocess.test_build_ib_bw_perf_chartandtest_build_ib_lat_perf_chartwriteib_bw_pps_perf.xlsxandib_lat_perf.xlsxin the current directory. A later process does not see the measurements.The latency chart fails with
No latency results for <test>when that test is present and has no rows.Node-local logs
/tmp/ib_perf_<gpu-index>_logsare removed at the start of every message size.Outlier marks in the HTML run deck do not fail the pytest test. Threshold misses do, when
verify_bwis on and a threshold exists for that point.
HIP_VISIBLE_DEVICES, ROCR_VISIBLE_DEVICES, CUDA_VISIBLE_DEVICES, and GPU_DEVICE_ORDINAL are cleared for the HIP device probe and for every perftest launch, so values set by a scheduler or in the cluster file env_vars do not change which GPU each perftest uses.