Run the Aorta training benchmark with CVS on AMD Instinct GPUs#
2026-10-26
9 min read time
Aorta runs an RCCL/training workload in containers, collects PyTorch profiler traces, and validates iteration time, compute ratio, overlap ratio and rank balance. Each run produces a pytest HTML report with one row per stage and a JSON benchmark report with the measured metrics.
Prerequisites#
In addition to the common training prerequisites:
Place Aorta at
aorta_pathon each node, or enableaorta_auto_cloneand provideaorta_clone_url.Passwordless
sudo dmesgfor the job user. The suite uses it to scan the kernel log for the benchmark window.
Set up config#
Copy a JSON variant and its sibling threshold file:
cvs config copy benchmark/aorta/mi3xx_aorta_profile_overlap_2gpu_single.json --output ./aorta_single.json
cvs config copy benchmark/aorta/mi3xx_aorta_profile_overlap_2gpu_distributed.json --output ./aorta_distributed.json
cvs config copy benchmark/aorta/mi3xx_aorta_profile_overlap_2gpu_threshold.json --output ./mi3xx_aorta_profile_overlap_2gpu_threshold.json
Replace every <changeme> in the selected variant. Set the repository storage path, GPU
count, and distributed fabric interfaces for your cluster. Place Aorta at aorta_path on
each node, or enable aorta_auto_clone and provide aorta_clone_url. Keep the configured
GPU count consistent with the selected Aorta YAML and profiling workload. On bare metal,
prefer writable local/scratch storage when root-squashed NFS prevents the container from
writing artifacts. Under SPUR or Slurm, aorta_path must be on shared storage; see
Run on managed compute.
Full parameter list: Aorta benchmark configuration file for Cluster Validation Suite (CVS).
Run tests#
Use one node with aorta_single or two or more with aorta_distributed:
cvs list aorta_single
cvs list aorta_distributed
cvs run aorta_single --cluster_file cluster-single.json --config_file aorta_single.json
cvs run aorta_distributed --cluster_file cluster-distributed.json --config_file aorta_distributed.json
Both suites run these stages in order:
Launch and verify containers.
Clone or verify Aorta on every node.
Verify torchrun and configured RDMA devices (distributed only).
Build RCCL unless
skip_rccl_buildis true.Launch the workload, poll every node’s exit status, and scan each node’s kernel log (
dmesg) for the benchmark window.Collect fresh profiler traces and execution logs.
Run optional TraceLens/GEMM analysis.
Parse results and validate thresholds.
Generate the JSON report and tear down.
A failed stage gates dependent stages. Trace collection, parsing of surviving artifacts, report generation and teardown remain possible after a distributed execution failure. Optional analysis failures fall back to raw traces. Multi-node metrics always use the collected raw traces, since head-node Excel reports cover only that node.
See Run on managed compute to run inside a scheduler job and Reports and outputs for the HTML report.
Run on managed compute#
Follow Run Cluster Validation Suite (CVS) on managed compute to run Aorta on managed compute.
Aorta adds these suite-specific requirements:
Request one node for
aorta_singleand two or more foraorta_distributed, with at leastgpus_per_nodeGPUs on each node.The generated cluster file uses each node’s hostname as its
vpc_ip, so torchrun rendezvous uses the first node’s hostname. To use a fabric address instead, either:Set
multi_node.master_addrin the Aorta config; orPass a
--cluster_filewhosenode_dictlists only this job’s nodes, with theirvpc_ip. Nodes outside the job are rejected.
Keep the config file, its sibling threshold file and
aorta_pathon storage that every node sees at the same path. If compute nodes cannot reachaorta_clone_url, clone Aorta from a login node and leaveaorta_auto_clonefalse.Set
output_dirto an absolute path on shared storage. A relativeoutput_dirresolves against the working directory ofcvs runon the job’s first node.CVS starts one torchrun process per node inside the Aorta containers.
Set the job time limit higher than
timeout_secondsplus the time for container launch and the RCCL build.
Reports and outputs#
Pytest HTML report#
cvs run writes the pytest HTML report and text log described in Pytest HTML report and bundle. Aorta names them after the suite: aorta_single.html and aorta_single.log, or aorta_distributed.html and aorta_distributed.log.
The report has one row per stage, in run order:
test_launch_containertest_clone_aortatest_setup_rdma(distributed only)test_build_rccltest_run_benchmarktest_collect_tracestest_analyzetest_parse_resultstest_validate_thresholdstest_generate_reporttest_teardown
Each row with captured output has a Full Log link. Skipped rows show the reason:
a prior lifecycle stage failed: an earlier stage failed. Start with the first failed row.skip_rccl_build=true: the config disabled the RCCL build.Optional TraceLens/GEMM analysis is disabled: the config disabled analysis.enforce_thresholds=false; metrics are recorded without threshold assertions: the config disabled threshold assertions.No parsed benchmark result available: parsing produced no result to report.
Threshold validation reports each configured threshold as a pytest sub-test
([threshold] (metric=<key>)), and trace collection reports each node it collected
from ([trace collection] (host=<node>)), plus a failed
[trace collection] (artifact=torch_traces) sub-test when no node produced usable
traces. Expand the test_validate_thresholds or test_collect_traces row to see
one row per sub-test. Threshold rows show the measured value (Actual) next to the
gate, and a failed row gives the reason. A failed sub-test also fails its parent row,
so dependent stages are gated and validation_passed is false. Kernel-log matches
and per-node launch failures appear on test_run_benchmark.
In the JUnit XML, each sub-test is a cvs_aorta_subtest property of the parent test
case whose value gives the outcome, the measured value and gate for thresholds, and any
failure message. JUnit keeps one <testcase> per stage, but each sub-test adds one
to the testsuite tests total, and a failed sub-test adds its own <failure>
to the parent <testcase> next to the parent’s failure.
Next to the report, aorta_single_html/ (or aorta_distributed_html/) holds
the per-stage logs and copies of the cluster and config files.
aorta_single_<timestamp>.zip (or aorta_distributed_<timestamp>.zip) bundles
the report with those files for sharing. The bundle does not contain Aorta traces
or the JSON report; those stay under output_dir.
The report also links the Aorta Run Deck; see Run Deck.
Benchmark artifacts#
CVS downloads artifacts to output_dir/<run-id>/ on the machine running CVS, which is
the job’s first node on managed compute. <run-id> is a new hexadecimal ID for each
invocation and is separate from the CVS <run_id> above. Distributed
traces use combined_traces/node_<rank>/<original-output>/torch_profiler/. The JSON report,
aorta_benchmark_report.json, records cluster configuration, aggregate performance,
per-rank summaries, execution status, validation status and collection errors. Benchmark and
RCCL logs are also downloaded. On bare metal over SSH, CVS copies these files from each
node, so no shared filesystem with the CVS machine is required. Under SPUR or Slurm, CVS
reads them from aorta_path on shared storage; see Run on managed compute.
Calibrate the sample thresholds for your hardware, node count and workload. Set
enforce_thresholds: false to record metrics without threshold assertions.
Run Deck#
The Aorta files are aorta_run_deck.html and
aorta_run_deck.json. The pytest report links the deck as “Aorta Run Deck”.
See Pytest HTML report and bundle for generic Run Deck behavior and
packaging. A run has one result, so Aorta has no interactive viewer.
The run card shows workload, framework, image, cluster dimensions, metrics
source, threshold state, one verdict with actual and limit per configured
threshold, pytest stage outcome, and links to the pytest report and log. The
lifecycle timeline shows each stage’s call duration. Threshold gates shows
iteration_time, compute_ratio, overlap_ratio, and rank_balance.
The benchmark result card summarizes the run, and the full results table lists
all reported metrics. Per-rank breakdown graphs time, share of iteration, and
communication overlap when there are at least two ranks; graph ratios are
percentages.
Deck JSON metric keys use the training. prefix, such as
training.avg_iteration_time_ms. Table and JSON ratios remain fractions in
the range 0..1, matching the threshold file. Iteration time is the parser’s
per-rank total_time_us averaged across ranks, and matches
avg_iteration_time_ms in aorta_benchmark_report.json. The reported
standard deviation, minimum, and maximum are across ranks. Time variance is
standard deviation divided by mean iteration time; it is absent when the mean
is zero. Compute and communication ratios are their respective times divided
by total time. Overlap is
max(0, compute + comm - total) / comm, or zero when comm is zero.
The metrics source depends on the parser path. Aorta TraceLens Excel reports and TraceLens parsing of raw traces use the GPU timeline; “comm” then means exposed communication time. The basic raw-trace scan, used when TraceLens is unavailable or fails for a rank, reports total communication-kernel time as “comm” and the sum of trace-event durations as “total”. The run card names the parser. Because per-rank fallback is not recorded, the deck uses the neutral label “Comm time”.
Each threshold verdict comes from the parser’s per-threshold validation call.
Null thresholds are omitted and appear as n/a in the gate matrix. With
enforce_thresholds: false, the deck shows record-only and overall status
record. When an earlier stage prevents threshold validation, it shows
not evaluated and overall status record. With no parsed metrics, overall
status is na. Overall status reflects threshold evaluation; the “Pytest
stages” row shows whether another stage failed.