ROCm stack health

Healthy (passing)

Every night AORTA installs the freshly built wheel on a reference MI350 runner and replays representative PyTorch workloads — training, inference, and distributed correctness checks — comparing each result against a blessed baseline when one exists.

aorta
0.3.1rc20261031
PyTorch
2.13.0+rocm10.0.0
ROCm
10.0.0
HIP
7.15.26333

Run of 2026-10-31 11:21 UTC · commit d22f611 · workflow run · amd_aorta-0.3.1rc20261031-py3-none-any.whl

Reference hardware: single-node MI350 runner with pinned ROCm + PyTorch wheels. Numbers are nightly CI references — not a guarantee on other AMD GPUs or cluster configurations.
results
18
pass
18
fail
0
record
0
skip
0
pass rate
100%
pass-rate trend

Category health

Worst verdict in each area from tonight's run. Click a tile to jump to workloads.

Platform
✓ pass
1 pass
Inference
✓ pass
1 pass
Serving
✓ pass
2 pass
Training
✓ pass
4 pass
Correctness
✓ pass
10 pass

What changed since 2026-10-30

and 6 more metrics past 10%

Nightly release health

Each card is one nightly release (newest first). Overall health summarises that night's graded verdicts; workload chips wrap instead of scrolling sideways. Active workloads link to reproduction steps below. Retired workloads (no longer in the latest matrix) are plain text. Glyphs: ✓ pass · ✗ fail · ◆ record · ○ skip.

Training scaling (2 → 8 GPU)

Reference step_time_p50 from the latest nightly. Recipes use the same per-rank batch at 2 and 8 GPUs (weak scaling), so ideal step time is flat. Efficiency is p50_2 / p50_8 as a percentage.

strategy2 GPU p508 GPU p50slowdownefficiency
DDP1.0 ms1.3 ms1.27×79%
FSDP5.6 ms6.0 ms1.08×93%

Workloads

Workloads are grouped by use case below. Each card shows tonight's recipe variants; expand Reproduce this workload locally for a full step-by-step guide, or Detailed metrics for additional summary values.

Platform

ROCm and PyTorch load and execute on GPU.

Verifies the ROCm/PyTorch stack loads and runs on GPU.

1 result · 1 pass · workload run 11s

Reproduce this workload locally
Before you start
  • One AMD GPU with working ROCm drivers
  • Python 3.10+ and a PyTorch build for your ROCm version
  • Network access to github.com/ROCm/aorta (clone + dev wheels)
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=1, f'need 1 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/ci/gpu-smoke.yaml --dry-run
4. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

aorta sweep run --recipe recipes/ci/gpu-smoke.yaml --output-dir triage_results/repro/gpu_smoke --strict
5. Read the smoke matrix
RUN_DIR="$(find triage_results/repro/gpu_smoke -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
Success criteria

Rank 0 prints `Wrote matrix to ...`. matrix.md shows every cell completed; mean_step_time_ms is recorded in perf.md. Nightly gates pass/fail against the blessed gpu_smoke::baseline-local baseline; step time is recorded but not performance-thresholded.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/ci/gpu-smoke.yaml · Multi-node launcher guide

baseline-localpass196.1 ms
  • step time: 196.1 ms
Detailed metrics (optional) — 3 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/ci/gpu-smoke.yaml · 1 trial

metricgrading rulethis runhistory
expectedtracked only (not gated)8
ntracked only (not gated)8
sumtracked only (not gated)8

Inference

Offline LLM prefill/decode latency and throughput.

Offline LLM inferenceinference_offline

Validates prefill/decode latency, throughput, and logits checksum.

1 result · 1 pass · workload run 18s

Reproduce this workload locally
Before you start
  • One AMD GPU with enough VRAM for the built-in smoke model
  • PyTorch with ROCm (the recipe uses AORTA's RepeatedBlockModel locally)
  • Same AORTA wheel channel as nightly when comparing checksums
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=1, f'need 1 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/inference/example-inference-smoke.yaml --dry-run
4. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

aorta sweep run --recipe recipes/inference/example-inference-smoke.yaml --output-dir triage_results/repro/inference_offline --strict
5. Inspect latency, throughput, and checksum artifacts
RUN_DIR="$(find triage_results/repro/inference_offline -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 10 -E "tokens_per_sec|prefill|decode|checksum" "$RUN_DIR/perf.md" 2>/dev/null || python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps(d.get(\"cells\",[]), indent=2)[:2000])" "$RUN_DIR/matrix.json"
Success criteria

Recipe completes with --strict. logits_checksum is the active correctness gate in regression_baselines.yaml; latency and throughput are recorded on the dashboard but not perf-gated yet.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/inference/example-inference-smoke.yaml · Multi-node launcher guide

baseline-localpass40.4 ms
  • tokens per sec: 3692 tok/s
  • prefill latency ms: 1.077 ms
  • decode latency ms: 1.083 ms
  • logits checksum: captured (33,904,201)
Detailed metrics (optional) — 10 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/inference/example-inference-smoke.yaml · 1 trial

metricgrading rulethis runhistory
batch_sizetracked only (not gated)4
decode_latency_mstracked only (not gated)1.083 ms
decoded_tokenstracked only (not gated)496
generate_tokenstracked only (not gated)32
logits_checksummust match baseline33,904,201
prefill_latency_mstracked only (not gated)1.077 ms
prompt_lentracked only (not gated)128
step_time_p50tracked only (not gated)38.58 ms
step_time_p99tracked only (not gated)45.81 ms
tokens_per_sectracked only (not gated)3692 tok/s

Serving

Online LLM serving latency (TTFT/TPOT) and token throughput.

TokenSpeed online servingtokenspeed_serve_smoke

Time to first token, time per output token, and token throughput from a containerised TokenSpeed server.

2 results · 2 pass · workload run 514s

Reproduce this workload locally
Before you start
  • One gfx950 (MI355X) or gfx1250 GPU — the TokenSpeed image targets these
  • A working docker client and daemon: the engine runs in its own container
  • A node-local work_dir — an NFS home under root-squash cannot be bind-mounted
  • Egress to the Hugging Face Hub, or a pre-populated cache plus hf_offline
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=1, f'need 1 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Serving-specific: pull the pinned engine image
docker pull lightseekorg/tokenspeed-amd@sha256:60c12e37c01496891053b9c30c4204e5d1cf9b4b641859d3aadcbd95bccc7c78
4. Serving-specific: pre-warm the model cache as the running uid
# The path is load-bearing. The workload derives its cache from
# workload_config.hf_home, falling back to <work_dir>/u<uid>/hf --
# it does not read an inherited HF_HOME, so a download into any
# other directory populates a cache the run never mounts and the
# first cell downloads the weights again regardless.
# run_as_current_user defaults to true, so download as the uid
# that will run the sweep: a cache populated by a root container
# leaves the trial failing with PermissionError.
mkdir -p /tmp/ts-work-serve/u$(id -u)/hf
HF_HOME=/tmp/ts-work-serve/u$(id -u)/hf hf download Qwen/Qwen3-0.6B
5. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/tokenspeed/tokenspeed-serve-bench-smoke.yaml --dry-run
6. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

aorta sweep run --recipe recipes/tokenspeed/tokenspeed-serve-bench-smoke.yaml --output-dir triage_results/repro/tokenspeed_serve_smoke --strict
7. Inspect serving latency and throughput artifacts
RUN_DIR="$(find triage_results/repro/tokenspeed_serve_smoke -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 10 -E "ttft|tpot|output_throughput|completed_total" "$RUN_DIR/perf.md" 2>/dev/null || python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps(d.get(\"cells\",[]), indent=2)[:2000])" "$RUN_DIR/matrix.json"
Success criteria

Both cells pass with completed_total == num_prompts * steps and failed_total == 0. median_ttft_ms / median_tpot_ms / output_throughput appear in perf.md. Two metrics are gated on both cells — median_tpot_ms and p99_itl_ms, ceilings from the 2026-09-08..09-17 window — so a run over either fails the nightly, and the breaching observation is still recorded and charted in this cell's history for diagnosis. Every other serving metric is still record-only, including step_time_ms.max; see docs/tokenspeed-gating-rollout.md for which metrics get bounds and why bring-up time never does (189-379s on one node with nothing changed).

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/tokenspeed/tokenspeed-serve-bench-smoke.yaml · Multi-node launcher guide

baselinepass1,201.8 ms
  • median ttft ms: 47.06
  • median tpot ms: 1.953
  • output throughput: 3408
Detailed metrics (optional) — 44 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/tokenspeed/tokenspeed-serve-bench-smoke.yaml · 1 trial

metricgrading rulethis runhistory
bench_stepstracked only (not gated)3
completed_totaltracked only (not gated)96
container_elapsed_sectracked only (not gated)243.1
durationtracked only (not gated)1.202
failed_totaltracked only (not gated)0
input_lentracked only (not gated)512
max_concurrencytracked only (not gated)8
max_concurrent_requeststracked only (not gated)32
max_output_tokens_per_stracked only (not gated)3407
mean_e2el_mstracked only (not gated)287.4
mean_itl_mstracked only (not gated)1.919
mean_tpot_mstracked only (not gated)1.874
mean_ttft_mstracked only (not gated)49.43
median_e2el_mstracked only (not gated)278.4
median_itl_mstracked only (not gated)0.001985
median_tpot_mslower is better1.953
median_ttft_mstracked only (not gated)47.06
num_promptstracked only (not gated)32
num_warmupstracked only (not gated)1
output_lentracked only (not gated)128
output_throughputtracked only (not gated)3408
p50_e2el_mstracked only (not gated)278.4
p50_itl_mstracked only (not gated)0.001985
p50_tpot_mstracked only (not gated)1.953
p50_ttft_mstracked only (not gated)47.06
p90_e2el_mstracked only (not gated)312.2
p90_itl_mstracked only (not gated)2.065
p90_tpot_mstracked only (not gated)2.069
p90_ttft_mstracked only (not gated)52.63
p99_e2el_mstracked only (not gated)313.8
p99_itl_mslower is better36.86
p99_tpot_mstracked only (not gated)2.088
p99_ttft_mstracked only (not gated)206.6
request_throughputtracked only (not gated)26.63
server_startup_sectracked only (not gated)184
std_e2el_mstracked only (not gated)18.23
std_itl_mstracked only (not gated)6.279
std_tpot_mstracked only (not gated)0.3553
std_ttft_mstracked only (not gated)42.21
tokens_per_sectracked only (not gated)3408 tok/s
total_input_tokenstracked only (not gated)16,384
total_output_tokenstracked only (not gated)4,096
total_token_throughputtracked only (not gated)1.704e+04
warmup_stepstracked only (not gated)2
no-scratch-reclaimpass1,197.8 ms
  • median ttft ms: 48.7
  • median tpot ms: 1.91
  • output throughput: 3420
Detailed metrics (optional) — 44 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/tokenspeed/tokenspeed-serve-bench-smoke.yaml · 1 trial

metricgrading rulethis runhistory
bench_stepstracked only (not gated)3
completed_totaltracked only (not gated)96
container_elapsed_sectracked only (not gated)256.9
durationtracked only (not gated)1.198
failed_totaltracked only (not gated)0
input_lentracked only (not gated)512
max_concurrencytracked only (not gated)8
max_concurrent_requeststracked only (not gated)32
max_output_tokens_per_stracked only (not gated)3428
mean_e2el_mstracked only (not gated)285.5
mean_itl_mstracked only (not gated)1.898
mean_tpot_mstracked only (not gated)1.853
mean_ttft_mstracked only (not gated)50.1
median_e2el_mstracked only (not gated)278
median_itl_mstracked only (not gated)0.5179
median_tpot_mslower is better1.91
median_ttft_mstracked only (not gated)48.7
num_promptstracked only (not gated)32
num_warmupstracked only (not gated)1
output_lentracked only (not gated)128
output_throughputtracked only (not gated)3420
p50_e2el_mstracked only (not gated)278
p50_itl_mstracked only (not gated)0.5179
p50_tpot_mstracked only (not gated)1.91
p50_ttft_mstracked only (not gated)48.7
p90_e2el_mstracked only (not gated)312.4
p90_itl_mstracked only (not gated)2.051
p90_tpot_mstracked only (not gated)2.066
p90_ttft_mstracked only (not gated)53.52
p99_e2el_mstracked only (not gated)315.2
p99_itl_mslower is better36.69
p99_tpot_mstracked only (not gated)2.085
p99_ttft_mstracked only (not gated)206.8
request_throughputtracked only (not gated)26.72
server_startup_sectracked only (not gated)199
std_e2el_mstracked only (not gated)18.44
std_itl_mstracked only (not gated)6.014
std_tpot_mstracked only (not gated)0.3523
std_ttft_mstracked only (not gated)42.33
tokens_per_sectracked only (not gated)3420 tok/s
total_input_tokenstracked only (not gated)16,384
total_output_tokenstracked only (not gated)4,096
total_token_throughputtracked only (not gated)1.71e+04
warmup_stepstracked only (not gated)2

Training

PyTorch DDP and FSDP training step times.

Distributed data parallel training step time on two GPUs.

1 result · 1 pass · workload run 21s

Reproduce this workload locally
Before you start
  • Two AMD GPUs on one node, visible to a single PyTorch process group
  • RCCL usable between the two devices (check PCIe/xGMI topology)
  • torchrun on PATH (ships with PyTorch)
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=2, f'need 2 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/training/example-training-ddp-smoke.yaml --dry-run
5. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=2 $(which aorta) sweep run --recipe recipes/training/example-training-ddp-smoke.yaml --output-dir triage_results/repro/training_ddp --strict
6. Confirm both ranks finished and step times recorded
RUN_DIR="$(find triage_results/repro/training_ddp -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 10 -E "step_time_p50|step_time_p99" "$RUN_DIR/perf.md" 2>/dev/null || python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps(d.get(\"cells\",[]), indent=2)[:2000])" "$RUN_DIR/matrix.json"
Success criteria

All ranks complete without error. step_time_p50/p99 appear in perf.md. Nightly currently records training cells (passed/recording only); step-time thresholds are not perf-gated in regression_baselines.yaml yet.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/training/example-training-ddp-smoke.yaml · Multi-node launcher guide

baseline-localpass1,240.0 ms
  • step time p50: 1.05 ms
  • step time p99: 3.345 ms
Detailed metrics (optional) — 3 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/training/example-training-ddp-smoke.yaml · 1 trial

metricgrading rulethis runhistory
final_losstracked only (not gated)6.937
step_time_p50tracked only (not gated)1.05 ms
step_time_p99tracked only (not gated)3.345 ms

Distributed data parallel training step time on eight GPUs.

1 result · 1 pass · workload run 28s

Reproduce this workload locally
Before you start
  • Eight AMD GPUs on one node (nightly reference: single MI350 node)
  • torchrun --standalone --nproc_per_node=8 must bind one rank per GPU
  • Enough host memory for eight concurrent training workers
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=8, f'need 8 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/training/example-training-ddp-smoke.yaml --dry-run
5. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=8 $(which aorta) sweep run --recipe recipes/training/example-training-ddp-smoke.yaml --output-dir triage_results/repro/training_ddp_8gpu --strict
6. Check weak-scaling step times on eight ranks
RUN_DIR="$(find triage_results/repro/training_ddp_8gpu -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 10 -E "step_time_p50" "$RUN_DIR/perf.md" 2>/dev/null || python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps(d.get(\"cells\",[]), indent=2)[:2000])" "$RUN_DIR/matrix.json"
Success criteria

All ranks complete without error. step_time_p50/p99 appear in perf.md. Nightly currently records training cells (passed/recording only); step-time thresholds are not perf-gated in regression_baselines.yaml yet. Compare 2-GPU vs 8-GPU step_time_p50 in the dashboard scaling section.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/training/example-training-ddp-smoke.yaml · Multi-node launcher guide

baseline-localpass1,255.0 ms
  • step time p50: 1.336 ms
  • step time p99: 55.33 ms
Detailed metrics (optional) — 3 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/training/example-training-ddp-smoke.yaml · 1 trial

metricgrading rulethis runhistory
final_losstracked only (not gated)6.937
step_time_p50tracked only (not gated)1.336 ms
step_time_p99tracked only (not gated)55.33 ms

Fully sharded data parallel training on two GPUs.

1 result · 1 pass · workload run 21s

Reproduce this workload locally
Before you start
  • Two AMD GPUs with FSDP-compatible PyTorch build
  • Same torchrun/NCCL setup as DDP (FSDP still uses dist.init_process_group)
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=2, f'need 2 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/training/example-training-fsdp-smoke.yaml --dry-run
5. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=2 $(which aorta) sweep run --recipe recipes/training/example-training-fsdp-smoke.yaml --output-dir triage_results/repro/training_fsdp --strict
6. Read FSDP step-time artifacts
RUN_DIR="$(find triage_results/repro/training_fsdp -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 10 -E "step_time_p50|step_time_p99" "$RUN_DIR/perf.md" 2>/dev/null || python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps(d.get(\"cells\",[]), indent=2)[:2000])" "$RUN_DIR/matrix.json"
Success criteria

All ranks complete without error. step_time_p50/p99 appear in perf.md. Nightly currently records training cells (passed/recording only); step-time thresholds are not perf-gated in regression_baselines.yaml yet.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/training/example-training-fsdp-smoke.yaml · Multi-node launcher guide

baseline-localpass1,184.2 ms
  • step time p50: 5.55 ms
  • step time p99: 59.5 ms
Detailed metrics (optional) — 3 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/training/example-training-fsdp-smoke.yaml · 1 trial

metricgrading rulethis runhistory
final_losstracked only (not gated)254.4
step_time_p50tracked only (not gated)5.55 ms
step_time_p99tracked only (not gated)59.5 ms

Fully sharded data parallel training on eight GPUs.

1 result · 1 pass · workload run 28s

Reproduce this workload locally
Before you start
  • Full eight-GPU node (nightly runs on a single MI350 host)
  • FSDP requires stable NCCL/RCCL across all eight ranks
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=8, f'need 8 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/training/example-training-fsdp-smoke.yaml --dry-run
5. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=8 $(which aorta) sweep run --recipe recipes/training/example-training-fsdp-smoke.yaml --output-dir triage_results/repro/training_fsdp_8gpu --strict
6. Confirm eight-rank FSDP artifacts
RUN_DIR="$(find triage_results/repro/training_fsdp_8gpu -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 10 -E "step_time_p50" "$RUN_DIR/perf.md" 2>/dev/null || python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps(d.get(\"cells\",[]), indent=2)[:2000])" "$RUN_DIR/matrix.json"
Success criteria

All ranks complete without error. step_time_p50/p99 appear in perf.md. Nightly currently records training cells (passed/recording only); step-time thresholds are not perf-gated in regression_baselines.yaml yet. Use the dashboard scaling table to compare 2-GPU vs 8-GPU FSDP efficiency.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/training/example-training-fsdp-smoke.yaml · Multi-node launcher guide

baseline-localpass1,285.4 ms
  • step time p50: 5.978 ms
  • step time p99: 58.26 ms
Detailed metrics (optional) — 3 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/training/example-training-fsdp-smoke.yaml · 1 trial

metricgrading rulethis runhistory
final_losstracked only (not gated)254.4
step_time_p50tracked only (not gated)5.978 ms
step_time_p99tracked only (not gated)58.26 ms

Correctness

Numerical determinism and distributed race detection.

Bit-exact repeatability across ranks; divergence indicates silent corruption.

4 results · 4 pass · workload run 77s

Reproduce this workload locally
Before you start
  • Two GPUs — determinism is checked across ranks in one job
  • Identical random seeds and deterministic PyTorch ops where required
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=2, f'need 2 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/llm-determinism/example-llm-determinism.yaml --dry-run
5. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=2 $(which aorta) sweep run --recipe recipes/llm-determinism/example-llm-determinism.yaml --output-dir triage_results/repro/llm_determinism --strict
6. Confirm ranks_with_divergence from perf.md or matrix.json
RUN_DIR="$(find triage_results/repro/llm_determinism -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 5 -E "ranks_with_divergence|diverge" "$RUN_DIR/perf.md" 2>/dev/null || true
python3 - "$RUN_DIR" <<'PY'
import json
from pathlib import Path
import sys

run = Path(sys.argv[1])
doc = json.loads((run / 'matrix.json').read_text(encoding='utf-8'))
out = {}
for cell in doc.get('cells') or []:
    values = []
    for raw in cell.get('trial_paths') or []:
        path = Path(raw)
        if not path.is_absolute() and not path.exists():
            path = run / path
        if path.is_dir():
            path = path / 'result.json'
        if not path.is_file():
            continue
        trial = json.loads(path.read_text(encoding='utf-8'))
        metrics = (trial.get('result') or {}).get('metrics') or {}
        if 'ranks_with_divergence' in metrics:
            values.append(metrics['ranks_with_divergence'])
    out[cell.get('name', '?')] = values or None
print(json.dumps(out, indent=2))
PY
Success criteria

ranks_with_divergence must be 0 for a pass. Any non-zero value means silent numerical corruption between ranks and should fail nightly CI.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/llm-determinism/example-llm-determinism.yaml · Multi-node launcher guide

baseline-bf16-24Lpass7,399.1 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)1
num_layerstracked only (not gated)24
ranks_with_divergencetracked only (not gated)0
bf16-12Lpass7,040.4 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)1
num_layerstracked only (not gated)12
ranks_with_divergencetracked only (not gated)0
moe4-bf16-12Lpass7,696.0 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)4
num_layerstracked only (not gated)12
ranks_with_divergencetracked only (not gated)0
tf32_off-bf16-24Lpass7,344.0 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)1
num_layerstracked only (not gated)24
ranks_with_divergencetracked only (not gated)0

LLM determinism (8 GPU)llm_determinism_8gpu

Bit-exact repeatability at full-node scale.

4 results · 4 pass · workload run 107s

Reproduce this workload locally
Before you start
  • Eight-GPU node — catches determinism bugs that only appear at scale
  • Stable RCCL collectives; any rank mismatch fails the workload
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=8, f'need 8 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/llm-determinism/example-llm-determinism.yaml --dry-run
5. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=8 $(which aorta) sweep run --recipe recipes/llm-determinism/example-llm-determinism.yaml --output-dir triage_results/repro/llm_determinism_8gpu --strict
6. Confirm ranks_with_divergence is zero on all eight ranks
RUN_DIR="$(find triage_results/repro/llm_determinism_8gpu -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 5 -E "ranks_with_divergence|diverge" "$RUN_DIR/perf.md" 2>/dev/null || true
python3 - "$RUN_DIR" <<'PY'
import json
from pathlib import Path
import sys

run = Path(sys.argv[1])
doc = json.loads((run / 'matrix.json').read_text(encoding='utf-8'))
out = {}
for cell in doc.get('cells') or []:
    values = []
    for raw in cell.get('trial_paths') or []:
        path = Path(raw)
        if not path.is_absolute() and not path.exists():
            path = run / path
        if path.is_dir():
            path = path / 'result.json'
        if not path.is_file():
            continue
        trial = json.loads(path.read_text(encoding='utf-8'))
        metrics = (trial.get('result') or {}).get('metrics') or {}
        if 'ranks_with_divergence' in metrics:
            values.append(metrics['ranks_with_divergence'])
    out[cell.get('name', '?')] = values or None
print(json.dumps(out, indent=2))
PY
Success criteria

ranks_with_divergence == 0 on every cell. This is a correctness gate, not a performance benchmark.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/llm-determinism/example-llm-determinism.yaml · Multi-node launcher guide

baseline-bf16-24Lpass8,807.5 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)1
num_layerstracked only (not gated)24
ranks_with_divergencetracked only (not gated)0
bf16-12Lpass8,260.0 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)1
num_layerstracked only (not gated)12
ranks_with_divergencetracked only (not gated)0
moe4-bf16-12Lpass9,201.5 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)4
num_layerstracked only (not gated)12
ranks_with_divergencetracked only (not gated)0
tf32_off-bf16-24Lpass9,056.2 ms
  • ranks with divergence: 0 ✓
Detailed metrics (optional) — 4 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/llm-determinism/example-llm-determinism.yaml · 1 trial

metricgrading rulethis runhistory
corruption_details_omittedtracked only (not gated)0
num_expertstracked only (not gated)1
num_layerstracked only (not gated)24
ranks_with_divergencetracked only (not gated)0

Detects timing races and silent data corruption in distributed layers.

1 result · 1 pass · workload run 21s

Reproduce this workload locally
Before you start
  • Two GPUs — race workload stresses concurrent RCCL + layer checksums
  • Race workloads use fresh process isolation per trial (see recipe)
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=2, f'need 2 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Race-specific: reserve trial master ports on static launchers
export AORTA_TRIAL_MASTER_PORT_BASE=30000
# Required for srun / static torchrun without elastic agent store
5. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/race/race_smoke.yaml --dry-run
6. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=2 $(which aorta) sweep run --recipe recipes/race/race_smoke.yaml --output-dir triage_results/repro/race --strict
7. Check layer checksum mismatches in matrix output
RUN_DIR="$(find triage_results/repro/race -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 5 -E "layer_checksum_mismatch" "$RUN_DIR/perf.md" 2>/dev/null || true
python3 - "$RUN_DIR" <<'PY'
import json
from pathlib import Path
import sys

run = Path(sys.argv[1])
doc = json.loads((run / 'matrix.json').read_text(encoding='utf-8'))
out = {}
for cell in doc.get('cells') or []:
    values = []
    for raw in cell.get('trial_paths') or []:
        path = Path(raw)
        if not path.is_absolute() and not path.exists():
            path = run / path
        if path.is_dir():
            path = path / 'result.json'
        if not path.is_file():
            continue
        trial = json.loads(path.read_text(encoding='utf-8'))
        metrics = (trial.get('result') or {}).get('metrics') or {}
        if 'layer_checksum_mismatches' in metrics:
            values.append(metrics['layer_checksum_mismatches'])
    out[cell.get('name', '?')] = values or None
print(json.dumps(out, indent=2))
PY
Success criteria

layer_checksum_mismatches must be 0. Non-zero values indicate detected races or silent corruption in distributed layers.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/race/race_smoke.yaml · Multi-node launcher guide

smokepass1,417.8 ms
  • layer checksum mismatches: 0 ✓
Detailed metrics (optional) — 10 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/race/race_smoke.yaml · 1 trial

metricgrading rulethis runhistory
avg_step_time_mstracked only (not gated)1418
corruption_details_omittedtracked only (not gated)0
declared_h2d_tensor_sizetracked only (not gated)1,000,000
eff_batch_sizetracked only (not gated)1
eff_ffn_sizetracked only (not gated)2,048
eff_num_headstracked only (not gated)4
eff_seq_lentracked only (not gated)512
effective_h2d_tensor_sizetracked only (not gated)1,000,000
layer_checksum_mismatchestracked only (not gated)0
layers_verifiedtracked only (not gated)15

Race detection at full-node scale.

1 result · 1 pass · workload run 28s

Reproduce this workload locally
Before you start
  • Eight-GPU node — amplifies timing races vs the 2-GPU smoke
  • Export AORTA_TRIAL_MASTER_PORT_BASE on static launchers (see README-running-recipes)
1. Check out the dashboard commit and install the matching AORTA wheel
git clone https://github.com/ROCm/aorta.git
cd aorta
git checkout d22f6116235c05395a0241a83d6f7e952a988454
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade --pre 'amd-aorta[hw-queue]==0.3.1rc20261031' -f https://github.com/ROCm/aorta/releases/expanded_assets/dev-wheels
# If that exact wheel is unavailable, pick the closest dev-wheel build
# and compare `aorta --version` with the dashboard header before reproducing.
aorta --help
2. Confirm ROCm + PyTorch see enough GPUs
python3 -c "import torch; n=torch.cuda.device_count(); assert torch.cuda.is_available() and n>0, 'no CUDA/HIP devices'; assert n>=8, f'need 8 GPU(s), have {n}'; print(f'{n} GPU(s), HIP', torch.version.hip)"
3. Export single-node torchrun env (adjust for multi-node)
export NCCL_DEBUG=WARN  # optional, for troubleshooting
export MASTER_ADDR=127.0.0.1
export MASTER_PORT=29500
# Slurm / multi-node: see recipes/README-running-recipes.md
4. Race-specific: reserve trial master ports on static launchers
export AORTA_TRIAL_MASTER_PORT_BASE=30000
5. Validate the recipe YAML (no GPU execution)
aorta sweep run --recipe recipes/race/race_smoke.yaml --dry-run
6. Run the recipe with --strict (same flag as nightly CI)

Run from the repository root after setup completes. A standalone --strict sweep only fails cells that error or never run. Dashboard pass/record/fail comes separately from nightly_eval.py comparing matrix.json against config/ci/regression_baselines.yaml; run that harness to apply the dashboard gates.

torchrun --standalone --nproc_per_node=8 $(which aorta) sweep run --recipe recipes/race/race_smoke.yaml --output-dir triage_results/repro/race_8gpu --strict
7. Confirm zero checksum mismatches at 8-GPU scale
RUN_DIR="$(find triage_results/repro/race_8gpu -mindepth 3 -maxdepth 3 -type d -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2-)"
if [ -z "$RUN_DIR" ] || [ ! -d "$RUN_DIR" ]; then echo "No run directory found"; exit 1; fi
echo "Using run directory: $RUN_DIR"
cat "$RUN_DIR/matrix.md"
python3 -m json.tool "$RUN_DIR/matrix.json" | head -80
if [ -f "$RUN_DIR/perf.md" ]; then head -60 "$RUN_DIR/perf.md"; else echo "(no perf.md)"; fi
# Standalone --strict only catches errored or not-run cells; dashboard pass/record/fail comes from nightly_eval.py separately comparing matrix.json to config/ci/regression_baselines.yaml
grep -m 5 -E "layer_checksum_mismatch" "$RUN_DIR/perf.md" 2>/dev/null || true
python3 - "$RUN_DIR" <<'PY'
import json
from pathlib import Path
import sys

run = Path(sys.argv[1])
doc = json.loads((run / 'matrix.json').read_text(encoding='utf-8'))
out = {}
for cell in doc.get('cells') or []:
    values = []
    for raw in cell.get('trial_paths') or []:
        path = Path(raw)
        if not path.is_absolute() and not path.exists():
            path = run / path
        if path.is_dir():
            path = path / 'result.json'
        if not path.is_file():
            continue
        trial = json.loads(path.read_text(encoding='utf-8'))
        metrics = (trial.get('result') or {}).get('metrics') or {}
        if 'layer_checksum_mismatches' in metrics:
            values.append(metrics['layer_checksum_mismatches'])
    out[cell.get('name', '?')] = values or None
print(json.dumps(out, indent=2))
PY
Success criteria

layer_checksum_mismatches == 0 for every cell. Any failure warrants inspecting per-trial JSON under cells/.

Compare with nightly numbers

Match the aorta, PyTorch, ROCm, and HIP versions shown in the dashboard header when comparing numbers. Small differences on different hardware are expected; regressions vs the blessed baseline are what nightly CI flags.

Recipe YAML: recipes/race/race_smoke.yaml · Multi-node launcher guide

smokepass1,626.4 ms
  • layer checksum mismatches: 0 ✓
Detailed metrics (optional) — 10 values

Additional summary metrics for this recipe variant. Grading rule is how nightly CI compares the value; this run is tonight; history is recent nights (when available).

recipe recipes/race/race_smoke.yaml · 1 trial

metricgrading rulethis runhistory
avg_step_time_mstracked only (not gated)1626
corruption_details_omittedtracked only (not gated)0
declared_h2d_tensor_sizetracked only (not gated)1,000,000
eff_batch_sizetracked only (not gated)1
eff_ffn_sizetracked only (not gated)2,048
eff_num_headstracked only (not gated)4
eff_seq_lentracked only (not gated)512
effective_h2d_tensor_sizetracked only (not gated)1,000,000
layer_checksum_mismatchestracked only (not gated)0
layers_verifiedtracked only (not gated)15

Results: pass/fail = compared against a blessed baseline · record = baseline not set yet · skip = not enough GPUs. Expand cards for reproduction steps or optional detailed metrics.

Latest ROCm canary · observed only

Tracks rocm/pytorch:latest, resolved to a concrete digest per run. Not a gate: these rows never affect the status above, the pass-rate trend, or any required check -- the merge gate stays on the digest pinned in docker/Dockerfile.ci-gpu. A change here says a new ROCm release moved something, which is a question to investigate, not a regression on this branch.

dateROCmtorchHIPbase imagepassed/gradednote
2026-10-18———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-19———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-20———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-21———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-22———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-23———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-24———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-25———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-26———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-27———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-28———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-29———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-30———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse
2026-10-31———sha256:099f59a3bee90/0canary produced no usable results document (exit 1); it failed before the evaluator wrote one, or wrote one that does not parse