Skip to main content

transferbench-debug

Use when a TransferBench (ROCm/CUDA bandwidth-benchmark) run fails, hangs, crashes, validates incorrectly, or produces unexpected/misleading results — i.e. the user is troubleshooting rather than ramping up usage. Covers reading error output, isolating hangs (single-rank vs. multi-rank, NIC vs. POD detection), validation failures, performance regressions, and the binary's built-in verbose / dump / dryrun introspection. Does NOT cover writing new configs from scratch (use the run-side skill) or modifying TransferBench source.

Source facts

Repository
ROCm/TransferBench
Last source activity
October 19, 2026 at 04:10
Detected SKILL.md language
English
Stars
80
Forks
29

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
5 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
transferbench-debug
description
Use when a TransferBench (ROCm/CUDA bandwidth-benchmark) run fails, hangs, crashes, validates incorrectly, or produces unexpected/misleading results — i.e. the user is troubleshooting rather than ramping up usage. Covers reading error output, isolating hangs (single-rank vs. multi-rank, NIC vs. POD detection), validation failures, performance regressions, and the binary's built-in verbose / dump / dryrun introspection. Does NOT cover writing new configs from scratch (use the run-side skill) or modifying TransferBench source.
# TransferBench debugging This skill kicks in when something is **wrong** with a TransferBench run. The goal is always: turn a vague "it doesn't work" into a specific failure mode with a known fix or workaround. ## Triage flow Always run these three steps **first** before guessing: 1. **Reproduce with the smallest possible config.** Replace presets with a single-line `cmdline` if possible; halve rank count; drop to one Transfer. 2. **Confirm the binary parses the input.** Run `dryrun` instead of executing — separates parser bugs from runtime bugs. 3. **Capture what the binary actually saw.** `TB_DUMP_CFG_FILE=out.cfg` for presets; `HIDE_ENV=0` (default) so the env-var summary at startup is visible. Only after that, branch by symptom — see the table below. ## Symptom → reference | Symptom | Most likely cause | First thing to try | Deeper | |---|---|---|---| | Process hangs at startup, no output | MPI bootstrap or socket-mode env vars wrong | `mpirun --tag-output` to confirm all ranks started; verify `TB_NUM_RANKS` matches `-np` | `references/multi-rank-debug.md` | | `Pod-aware` preset hangs or errors out before transfers | AMD-SMI / NVML pod detection unavailable | `TB_FORCE_SINGLE_POD=1` | `references/common-failures.md` §pod | | RDMA preset (nicp2p, nica2a, …) hangs in NIC bring-up | GID index, IB port, or NIC filter wrong | Lower `IB_GID_INDEX` to a known good index; `TB_NIC_FILTER` to a single NIC | `references/multi-rank-debug.md` §rdma | | Validation failure (`ALWAYS_VALIDATE=1` reports mismatch) | Wrong CU mask, wrong memory type, or actual HW issue | `VALIDATE_DIRECT=1`; rerun with `NUM_ITERATIONS=1` to see if first iter is wrong | `references/common-failures.md` §validation | | Bandwidth far below expected | Stream/HW-queue serialization, wrong executor, GFX kernel mis-tuned | `USE_SINGLE_STREAM=0` + `GPU_MAX_HW_QUEUES=8`; try `D` (DMA) instead of `G` | `references/common-failures.md` §perf | | Bandwidth varies wildly run-to-run | Warmup too short, NUMA/clock policy | `NUM_WARMUPS=10`, `SHOW_ITERATIONS=1`, `SHOW_PERCENTILES=50,90,99` | `references/common-failures.md` §perf | | Crash / segfault | Bad memory code (e.g. `F` on a GPU without fine-grain), bad kernel for arch | Run with `dryrun` first; rebuild without optimization for symbol info | `references/common-failures.md` §crash | | "Unsupported" / executor missing | Build-time disable (e.g. `DISABLE_NIC_EXEC=1`, `DISABLE_POD_COMM=1`) | `./TransferBench` (no args) — its banner lists which executors are compiled in | `references/common-failures.md` §unsupported | | Output is garbled / interleaved across ranks | MPI stderr buffering, no per-rank labels | `mpirun --tag-output` or pipe each rank into a per-rank log | `references/multi-rank-debug.md` §output | ## The four "always-on" introspection commands These four commands are how you **observe** the binary as it actually exists on this host (don't trust any documentation, including this one, when troubleshooting): ```bash ./TransferBench # banner: detected GPUs, NUMA, NICs, compiled features ./TransferBench help # config-file syntax with examples ./TransferBench presets # list of presets compiled into THIS build ./TransferBench envvars # complete list of env vars THIS build honors ``` Plus two safe inspections of any preset/config: ```bash ./TransferBench dryrun "<expression>" # validate parsing, expand wildcards TB_DUMP_CFG_FILE=dump.cfg ./TransferBench p2p # dump what a preset actually emits ``` ## Verbose / capture env vars Reach for these when you need more visibility (full table in `references/verbose-introspection.md`): | Env var | Effect | |---|---| | `HIDE_ENV=0` (default) | Print env-var summary at start (shows what was actually set) | | `SHOW_ITERATIONS=1` | Per-iteration timings — exposes warmup/jitter issues | | `SHOW_PERCENTILES=50,90,99` | Tail latencies — exposes slow-iteration outliers | | `ALWAYS_VALIDATE=1` | Validate destination after every iteration (slow, but catches data-corruption regressions) | | `VALIDATE_DIRECT=1` | Validate by reading the destination directly (skips copy-back path) | | `VALIDATE_SOURCE=1` | Confirm src was unchanged (catches kernels that overwrite src) | | `NUM_ITERATIONS=1` | Run exactly one iteration — useful when validation fails on iter N>0 | | `NUM_WARMUPS=0` | Strip warmups so iter-0 timing is the cold case | | `USE_INTERACTIVE=1` | Pause between tests — useful for `gdb attach` mid-run | | `TB_DUMP_CFG_FILE=out.cfg` | Dump executed Transfers from a preset to a config file | | `TB_DUMP_LINES=N` | Limit number of dumped lines | | `TB_VERBOSE=1` | Verbose lifecycle logging for newer execution paths (anvil/SDMA in recent builds) | | `TB_WALLCLOCK_RATE=<hz>` | Override GPU wallclock rate when the GPU returns 0 (debug-only) | ## Multi-rank-specific quick checks When debugging across nodes, before suspecting TransferBench itself: 1. **Same binary on every node.** `md5sum ./TransferBenchCuda` on each host. A different mtime/checksum is the most common multi-rank gotcha. 2. **Same env on every rank.** Use `mpirun -x VAR` (not just shell-export); without `-x`, only rank 0 sees your shell vars. 3. **Network actually up.** `ibstatus` (RDMA) or a `nc` between hosts on your master port (socket mode). 4. **Hostfile slots = 1 per node.** TransferBench expects one rank per node by default. ## When you're stuck If the table above and the references didn't help: 1. Build with `-g -O0` (or `-g -O1`) to get usable symbols, run under `gdb` / `cuda-gdb` / `rocgdb`, and `bt` once it hangs or crashes. Hangs in particular are usually obvious from the stuck thread's stack. 2. Strip the build down: pass `DISABLE_*` flags for any executor not under test (`DISABLE_NIC_EXEC=1`, `DISABLE_POD_COMM=1`, etc.). Eliminates whole code paths from suspicion. 3. Compare against a known-good commit. The `git log` on this repo has many tagged commits where features were added — you can check out an older commit, run the same config, and confirm it passes there. ## References - `references/common-failures.md` — symptom-organized catalog with concrete fixes - `references/multi-rank-debug.md` — MPI / socket / RDMA-specific issues - `references/verbose-introspection.md` — every debug-flavored env var + when to reach for it - `examples/topology-probe.sh` — minimal script that prints what TransferBench sees about the host
View on GitHub