CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
471 lines
18 KiB
Markdown
471 lines
18 KiB
Markdown
# rocSHMEM Deadlock Analysis Tools
|
|
|
|
Scripts for identifying and diagnosing deadlocks in rocSHMEM applications using
|
|
AMD's ROCm debugger (`rocgdb`).
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
|---|---|
|
|
| `rocgdb_deadlock_analysis.py` | rocgdb Python script: coalesces GPU wavefront backtraces, identifies rocSHMEM API entry points, and provides deadlock hints |
|
|
| `attach_deadlock_analysis.sh` | Shell wrapper: finds all running instances of an executable on the local node, attaches to each, saves per-process output, prints a compact summary |
|
|
| `mpiexec_deadlock_analysis.sh` | Multi-node wrapper: deploys `attach_deadlock_analysis.sh` to every node via mpiexec, then runs cross-rank coalescing |
|
|
| `cross_rank_deadlock_analysis.py` | Cross-rank coalescer: reads per-rank output files, groups identical backtrace patterns across ranks, highlights patterns uncommon among ranks |
|
|
| `deadlock_test.cc` | Intentional-deadlock test program used to validate the scripts |
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- `rocgdb` in `PATH` (provided by ROCm; override path with `ROCGDB` env var)
|
|
- `timeout` command (standard on Linux)
|
|
- Python support in rocgdb (built-in for ROCm 6+)
|
|
|
|
For meaningful backtraces the application and rocSHMEM library should be built
|
|
with debug symbols. A `RelWithDebInfo` build (CMake `-DCMAKE_BUILD_TYPE=RelWithDebInfo`)
|
|
gives full inlined call chains while keeping optimized performance. A `Release`
|
|
build will still show the outermost non-inlined API frame but not the internal
|
|
wait loops.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 1. Start your (deadlocked) application
|
|
mpirun -np 4 ./my_rocshmem_app &
|
|
|
|
# 2. Attach to all instances, analyze, save output
|
|
./scripts/debug/attach_deadlock_analysis.sh my_rocshmem_app
|
|
|
|
# Output is written to ./rocshmem_deadlock_analysis_<timestamp>/
|
|
# A compact summary is printed to stdout.
|
|
```
|
|
|
|
---
|
|
|
|
## `attach_deadlock_analysis.sh`
|
|
|
|
### Usage
|
|
|
|
```
|
|
attach_deadlock_analysis.sh <executable_name> [--directory <dir>] [--cull[=p1,p2,...]]
|
|
```
|
|
|
|
| Argument | Description |
|
|
|---|---|
|
|
| `executable_name` | Exact process name to search for |
|
|
| `--directory <dir>` | Directory for per-process output files (default: `./rocshmem_deadlock_analysis_<timestamp>/`) |
|
|
| `--cull` | Cull groups stuck in GPU barriers / gridsync using the built-in default pattern list |
|
|
| `--cull=p1,p2,...` | Cull groups whose backtrace contains any of the comma-separated substrings |
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|---|---|---|
|
|
| `ROCGDB` | `rocgdb` | Path to the rocgdb binary |
|
|
| `ROCSHMEM_GDB_TIMEOUT` | `120` | Per-process timeout in seconds |
|
|
| `ROCSHMEM_DEADLOCK_COLOR` | `always` | Color mode for output files (see [Color Support](#color-support)) |
|
|
|
|
### Output Files
|
|
|
|
Each analyzed process produces a file named:
|
|
|
|
```
|
|
<output_dir>/pe<PE_RANK>_pid_<PID>.txt
|
|
```
|
|
|
|
The MPI PE rank is read from the process's `OMPI_COMM_WORLD_RANK` environment
|
|
variable. If the variable is not set (non-MPI process or already exited), the
|
|
rank is shown as `unknown`.
|
|
|
|
### Stdout Summary
|
|
|
|
After all processes are analyzed, a compact summary is printed:
|
|
|
|
```
|
|
=== Attach and Analyze Summary ===
|
|
Processes analyzed: 2 / 2
|
|
|
|
PE 0 PID 12345 groups=? (no GPU threads found)
|
|
PE 1 PID 12346 groups=1 Waiting for remote PE memory update...
|
|
|
|
Full output in: ./rocshmem_deadlock_analysis_20260416_143022/
|
|
```
|
|
|
|
- **groups** — number of distinct backtrace groups found in that process
|
|
- **dominant** — the most frequent `[HINT]` line across all groups, or a
|
|
status string if no deadlock was detected
|
|
|
|
### Error Handling
|
|
|
|
| Situation | Behavior |
|
|
|---|---|
|
|
| Process exits before attach | Logged as SKIP, counted as failure |
|
|
| `rocgdb` exceeds timeout | Logged as TIMEOUT; output file kept for inspection |
|
|
| `rocgdb` exits non-zero but produced analysis | Still counted as success |
|
|
| `rocgdb` not found in `PATH` | Fatal error with hint to set `ROCGDB` |
|
|
|
|
---
|
|
|
|
## `rocgdb_deadlock_analysis.py`
|
|
|
|
The Python script can be used in three modes.
|
|
|
|
### Mode 1: Batch attach (used by `attach_deadlock_analysis.sh`)
|
|
|
|
Attach `rocgdb` to a running process and analyze immediately:
|
|
|
|
```bash
|
|
ROCSHMEM_DEADLOCK_AUTO_ANALYZE=1 \
|
|
rocgdb -batch -p <pid> -x scripts/debug/rocgdb_deadlock_analysis.py
|
|
```
|
|
|
|
The `ROCSHMEM_DEADLOCK_AUTO_ANALYZE=1` variable tells the script to run the
|
|
analysis as soon as the process is stopped (which happens automatically on
|
|
attach).
|
|
|
|
### Mode 2: Interactive session
|
|
|
|
Attach `rocgdb` manually, then source and run the script:
|
|
|
|
```
|
|
rocgdb -p <pid>
|
|
(rocgdb) source scripts/debug/rocgdb_deadlock_analysis.py
|
|
(rocgdb) rocshmem-deadlock-analyze
|
|
```
|
|
|
|
Write the report to a file:
|
|
|
|
```
|
|
(rocgdb) rocshmem-deadlock-analyze /tmp/analysis.txt
|
|
```
|
|
|
|
Force colored output in the file:
|
|
|
|
```
|
|
(rocgdb) rocshmem-deadlock-analyze --color /tmp/analysis.txt
|
|
```
|
|
|
|
### Mode 3: Launch mode
|
|
|
|
Run the application under rocgdb from the start; analysis triggers on first
|
|
stop (e.g. `pkill --signal SIGINT my_rocshmem_app`), or when the program crashes:
|
|
```bash
|
|
mpirun -n 2 -x ROCSHMEM_DEADLOCK_AUTO_ANALYZE=1 rocgdb -batch \
|
|
-x scripts/debug/rocgdb_deadlock_analysis.py \
|
|
-ex run \
|
|
--args ./my_rocshmem_app arg1 arg2
|
|
|
|
### GDB Command Reference
|
|
|
|
After sourcing the script, the `rocshmem-deadlock-analyze` command is available:
|
|
|
|
```
|
|
(rocgdb) rocshmem-deadlock-analyze [--color|--no-color] [--cull[=pat,...]] [--check-lanes] [output_file]
|
|
```
|
|
|
|
| Option | Description |
|
|
|---|---|
|
|
| `--color` | Force ANSI color codes on, even when writing to a file |
|
|
| `--no-color` | Disable color codes, even on a TTY |
|
|
| `--cull` | Cull groups stuck in GPU barriers / gridsync using the built-in default pattern list |
|
|
| `--cull=p1,p2,...` | Cull groups whose backtrace contains any of the comma-separated substrings |
|
|
| `--check-lanes` | Enable lane-level parameter mismatch detection for `_wg` and `_wave` collective calls (slow; see below) |
|
|
| `--stats` | Append a `=== rocSHMEM Stats ===` section with non-zero API call counters (requires `-DPROFILE=ON` build) |
|
|
| `output_file` | Write report to this file instead of stdout |
|
|
|
|
#### Cull option
|
|
|
|
When `--cull` is given without a pattern list, the following substrings are used to remove groups
|
|
that are simply waiting at a non-rocSHMEM GPU synchronization primitive (and are therefore not
|
|
rocSHMEM deadlocks):
|
|
|
|
| Pattern | Covers |
|
|
|---|---|
|
|
| `__syncthreads` | HIP workgroup barrier and reduction variants (`_count`, `_and`, `_or`) |
|
|
| `__builtin_amdgcn_s_barrier` | Direct AMDGCN scalar barrier intrinsic |
|
|
| `__work_group_barrier` | Workgroup barrier with memory-fence flags |
|
|
| `__named_sync` | Named barrier intrinsic |
|
|
| `__ockl_grid_sync` | OCKL grid-level synchronization |
|
|
| `__ockl_gws_barrier` | OCKL global-workspace barrier |
|
|
| `__ockl_multi_grid_sync` | OCKL multi-grid synchronization |
|
|
| `cooperative_groups` | HIP cooperative groups (`grid_group`, `thread_block`, `multi_grid_group`) |
|
|
|
|
Culled groups are not shown in the report; the header prints a count of how many
|
|
groups and wavefronts were removed:
|
|
|
|
```
|
|
Unique backtrace groups: 1
|
|
(+ 3 group(s) / 192 wavefront(s) culled — GPU barrier / gridsync)
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|---|---|---|
|
|
| `ROCSHMEM_DEADLOCK_AUTO_ANALYZE` | `0` | Set to `1` to trigger analysis automatically on process stop |
|
|
| `ROCSHMEM_DEADLOCK_COLOR` | `always` | Color mode (see [Color Support](#color-support)) |
|
|
|
|
---
|
|
|
|
## Output Format
|
|
|
|
```
|
|
=== rocSHMEM Deadlock Analysis ===
|
|
Process(es): 12346
|
|
Total GPU wavefronts analyzed: 64
|
|
Unique backtrace groups: 2
|
|
|
|
--- Group 1 (63 wavefront(s)) ---
|
|
WFs: (0,0,0)/0,(1,0,0)/0,(2,0,0)/0,...
|
|
Backtrace:
|
|
#0 rocshmem::uncached_load<long volatile> (...) at src/assembly.hpp:125
|
|
#1 rocshmem::Context::test<long> (...) at src/context_tmpl_device.hpp:432
|
|
#2 rocshmem::Context::wait_until<long> (...) at src/context_tmpl_device.hpp:224
|
|
#3 rocshmem::IPCContext::internal_direct_barrier (...) at ...
|
|
...
|
|
#7 rocshmem::Context::barrier_all_wg (...) at src/context_device.cpp:151
|
|
#8 my_kernel () at my_app.cpp:42
|
|
[HINT] Waiting for remote PE memory update (barrier/sync or user
|
|
rocshmem_wait_until). Check if the remote PE is alive and making
|
|
progress.
|
|
|
|
--- Group 2 (1 wavefront(s)) ---
|
|
WGs: (0,0,0) WFs: 0
|
|
Backtrace:
|
|
#0 rocshmem::acquire_lock (...) at src/gda/mlx5/queue_pair_mlx5.cpp:53
|
|
#1 rocshmem::QueuePair::mlx5_post_wqe_rma (...) at ...
|
|
#2 rocshmem::GDAContext::put (...) at ...
|
|
#3 rocshmem::rocshmem_ctx_put (...) at ... <<< rocSHMEM API entry
|
|
#4 my_kernel () at my_app.cpp:38
|
|
[rocSHMEM] Stuck in: rocshmem_ctx_put
|
|
[HINT] Waiting for SQ spinlock held by another wavefront. The lock holder
|
|
may itself be deadlocked in mlx5_poll_cq_until.
|
|
|
|
=== Summary ===
|
|
1 wavefront(s) inside rocSHMEM
|
|
63 wavefront(s) outside rocSHMEM
|
|
```
|
|
|
|
### Reading the Output
|
|
|
|
**Groups** — Wavefronts with identical backtraces (after stripping runtime-variable
|
|
parts like addresses and argument values) are coalesced into a single group.
|
|
Each group shows which workgroups (WGs) and wavefronts (WFs) share that call
|
|
stack. Template parameters and source file locations are kept in the key, so
|
|
`wait_until<int>` and `wait_until<long>` at different call sites produce
|
|
separate groups.
|
|
|
|
**`<<< rocSHMEM API entry`** — Marks the outermost rocSHMEM public API function
|
|
in the backtrace: the call the application made that led to the deadlock.
|
|
|
|
**`[rocSHMEM] Stuck in:`** — Names the matched API function for easy grepping.
|
|
|
|
**`[HINT]`** — A short diagnosis of the likely deadlock cause based on the
|
|
innermost recognized frame.
|
|
|
|
The innermost deadlock frame (the actual spinning loop) is printed in bold cyan.
|
|
|
|
**`=== Collective API Usage Issues ===`** — Appears after the per-group section
|
|
when incorrect `_wg` or `_wave` API usage is detected from the backtraces.
|
|
Three kinds of violations are reported:
|
|
|
|
| Issue | Description |
|
|
|---|---|
|
|
| `[BAD] … non-collective _wg call` | Wavefronts in the same workgroup are at different `_wg` API calls, or some are not in any `_wg` call. All wavefronts in a WG must call the same `_wg` primitive together. |
|
|
| `[BAD] … parameter mismatch in rocshmem_*_wg` | All wavefronts in a WG are at the same `_wg` call but with different argument values (e.g., different `pe` or `nelems`). |
|
|
|
|
`_wave` primitives are collective only within a single wavefront (all 64 lanes
|
|
must call with matching parameters). Different wavefronts — even in the same WG —
|
|
may independently call any `_wave` function with different parameters; that is valid.
|
|
Lane-level divergence within a wavefront is not visible from wavefront-level
|
|
backtraces and requires `--check-lanes` to detect.
|
|
|
|
#### Backend statistics (`--stats`)
|
|
|
|
When `--stats` is given, the script reads the rocSHMEM API call counters
|
|
directly from the stopped process's host memory without calling any function
|
|
in the inferior. The counters live in `Backend::globalStats` (device-side,
|
|
written by GPU `atomicAdd`) and `Backend::globalHostStats` (host-side,
|
|
written by `std::atomic`). Both arrays are in `hipHostMalloc`-pinned
|
|
memory, accessible to gdb without any cache flush.
|
|
|
|
Only non-zero counters are printed, grouped by device and host:
|
|
|
|
```
|
|
=== rocSHMEM Stats ===
|
|
PE 1
|
|
(counters reflect activity since process start)
|
|
Device:
|
|
put 8192
|
|
quiet 64
|
|
barrier_all_wg 4
|
|
Host:
|
|
(all zero)
|
|
```
|
|
|
|
> **Requires `-DPROFILE=ON`** at CMake build time. Without that flag
|
|
> `ROCStats` and `ROCHostStats` are empty `NullStats<N>` structs (no
|
|
> storage; all counters read as zero). The section will note when this
|
|
> is the case.
|
|
|
|
The counters count operations since process start, not since the deadlock.
|
|
They show what the application was doing before it got stuck — e.g. a high
|
|
`barrier_all_wg` count with a non-zero `put` count suggests the collective
|
|
stalled after a put-heavy phase.
|
|
|
|
#### Lane-level parameter mismatch (`--check-lanes`)
|
|
|
|
When `--check-lanes` is added to the `rocshmem-deadlock-analyze` command, the
|
|
script iterates over the active lanes of every wavefront that is inside a `_wg`
|
|
or `_wave` collective call. It switches rocgdb to each active lane, collects
|
|
the per-lane backtrace, and extracts the argument values for the collective
|
|
API frame.
|
|
|
|
If any two active lanes in the same wavefront disagree on a parameter, a
|
|
`LANE_PARAM_MISMATCH` issue is reported:
|
|
|
|
```
|
|
=== Collective API Usage Issues ===
|
|
[BAD] WG (0,0,0) WF 0 — lane parameter mismatch in rocshmem_putmem_wave (_wave contract)
|
|
Differing parameter(s): pe
|
|
Lane 0 [0,0,0]: pe=0
|
|
Lane 1 [1,0,0]: pe=1
|
|
Lane 2 [2,0,0]: pe=0
|
|
...
|
|
```
|
|
|
|
This check covers both `_wave` (lanes diverging within one wavefront) and `_wg`
|
|
(lanes in a wavefront that should present unified parameters to the WG-wide
|
|
collective).
|
|
|
|
> **Performance note:** `--check-lanes` issues up to 64 additional `bt` calls per
|
|
> wavefront in a collective call. On a busy kernel with many wavefronts this can
|
|
> be slow (several minutes). Use it only when wavefront-level analysis has
|
|
> already identified a collective call of interest.
|
|
|
|
### Recognized Deadlock Patterns and Hints
|
|
|
|
#### mlx5 (Mellanox/ConnectX) backend
|
|
|
|
| Innermost frame | Hint |
|
|
|---|---|
|
|
| `mlx5_poll_cq_until` | Waiting for NIC completion (CQ polling). Check if NIC is responsive and if the remote PE is also stuck. |
|
|
| `acquire_lock` | Waiting for SQ spinlock held by another wavefront. The lock holder may itself be deadlocked in `mlx5_poll_cq_until`. |
|
|
| `mlx5_quiet` | Quiet operation waiting for all outstanding RMA ops to complete. Check NIC health. |
|
|
|
|
#### bnxt (Broadcom) backend
|
|
|
|
| Innermost frame | Hint |
|
|
|---|---|
|
|
| `bnxt_poll_cq_until` | Waiting for NIC completion (CQ polling). Check if the bnxt NIC is responsive and if the remote PE is also stuck. |
|
|
| `bnxt_post_wqe_rma` | Waiting for bnxt SQ spinlock held by another wavefront. The lock holder is likely itself deadlocked in `bnxt_poll_cq_until`. |
|
|
| `bnxt_quiet` | Quiet operation waiting for all outstanding RMA ops to complete (bnxt). Check NIC health. |
|
|
|
|
#### ionic (AMD/Pensando) backend
|
|
|
|
| Innermost frame | Hint |
|
|
|---|---|
|
|
| `ionic_quiet_internal_ccqe_single` | Waiting for NIC completion in CCQE mode (single-thread path). Check if the ionic NIC is responsive and if the remote PE is also stuck. |
|
|
| `ionic_quiet_internal_ccqe` | Waiting for NIC completion in CCQE mode. Check if the ionic NIC is responsive and if the remote PE is also stuck. |
|
|
| `ionic_quiet_internal` | Waiting for NIC completion (CQ polling). Check if the ionic NIC is responsive and if the remote PE is also stuck. |
|
|
| `spin_lock_acquire_unique` | Waiting for ionic SQ doorbell spinlock (exclusive) held by another wavefront. The lock holder may itself be stuck in `ionic_quiet_internal`. |
|
|
| `spin_lock_acquire_shared` | Waiting for ionic CQ spinlock (shared) held by another wavefront. The lock holder may itself be stuck in `ionic_quiet_internal`. |
|
|
| `ionic_quiet` | Quiet operation waiting for all outstanding RMA ops to complete (ionic). Check NIC health. |
|
|
|
|
#### Shared / IPC / user-level waits (all backends)
|
|
|
|
| Innermost frame | Hint |
|
|
|---|---|
|
|
| `wait_until_any` | Waiting for any element of a multi-element condition. Check if the remote PE is alive. |
|
|
| `wait_until_all` | Waiting for all elements of a multi-element condition. Check if the remote PE is alive. |
|
|
| `wait_until_some` | Waiting for some elements of a multi-element condition. Check if the remote PE is alive. |
|
|
| `wait_until` | Waiting for remote PE memory update (barrier/sync or user wait). Check if the remote PE is alive. |
|
|
|
|
---
|
|
|
|
## Color Support
|
|
|
|
Color is controlled by the `ROCSHMEM_DEADLOCK_COLOR` environment variable:
|
|
|
|
| Value | Behavior |
|
|
|---|---|
|
|
| `always` (default) | Always enable ANSI color codes |
|
|
| `auto` | Enable color when the output is a TTY; disable for files |
|
|
| `1`, `yes`, `true` | Always enable ANSI color codes |
|
|
| `0`, `no`, `false`, `never` | Always disable color codes |
|
|
|
|
Color can also be forced per-invocation with the `--color` / `--no-color`
|
|
flags of the interactive `rocshmem-deadlock-analyze` command.
|
|
|
|
The shell script's stdout summary is always plain text; ANSI codes are
|
|
stripped from the per-process output files before extracting the dominant hint.
|
|
|
|
### Color Scheme
|
|
|
|
| Element | Color |
|
|
|---|---|
|
|
| Section headers (`=== ... ===`) | Bold blue |
|
|
| Group headers (`--- Group N ---`) | Bold bright blue |
|
|
| Innermost deadlock frame | Bold cyan |
|
|
| `<<< rocSHMEM API entry` annotation | Bold green |
|
|
| `[rocSHMEM] Stuck in:` line | Bold bright red |
|
|
| `[HINT]` line | Bold cyan |
|
|
| Stuck-wavefront count in summary | Bold bright red |
|
|
| Not-stuck count in summary | Bold green |
|
|
| "No GPU threads found" notice | Red |
|
|
|
|
---
|
|
|
|
## Building with Debug Symbols
|
|
|
|
Full call-chain visibility requires debug symbols in the rocSHMEM library and
|
|
the application. Use `RelWithDebInfo` for the best balance of performance and
|
|
debuggability:
|
|
|
|
```bash
|
|
# Configure the rocSHMEM build tree
|
|
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo <source_dir>
|
|
cmake --build . --target rocshmem --parallel 8
|
|
|
|
# Compile the application with matching flags
|
|
hipcc -O2 -g -fgpu-rdc -x hip my_app.cc \
|
|
--offload-arch=<target> \
|
|
-I<rocshmem_include> -I<mpi_include> \
|
|
-c -o my_app.o
|
|
|
|
hipcc -fgpu-rdc --hip-link my_app.o \
|
|
--offload-arch=<target> \
|
|
<rocshmem_lib>/librocshmem.a <mpi_lib>/libmpi.so \
|
|
-L/opt/rocm/lib -lamdhip64 -lhsa-runtime64 \
|
|
-o my_app
|
|
```
|
|
|
|
Without debug symbols only the outermost non-inlined frame is visible. The
|
|
`<<< rocSHMEM API entry` annotation still works (those functions are marked
|
|
`__attribute__((noinline))`), but the `[HINT]` requires the inner frames
|
|
(`wait_until`, `mlx5_poll_cq_until`, etc.) to be present.
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
- **IPC backend**: `rocshmem_barrier_all_wg` and related functions are fully
|
|
inlined in the IPC backend even at `RelWithDebInfo`. The `[rocSHMEM] Stuck in:`
|
|
line will not appear, but the `[HINT]` fires from the inner `wait_until` frame.
|
|
|
|
- **Release builds**: Without debug symbols, internal frames (`wait_until`,
|
|
`mlx5_poll_cq_until`, etc.) are invisible and no `[HINT]` is generated.
|
|
The API entry frame is still detected when it is non-inlined.
|
|
|
|
- **Lane-level analysis performance**: `--check-lanes` issues up to 64 `bt` calls
|
|
per wavefront in a collective call. On large kernels this can take several minutes.
|
|
|
|
- **Single GPU per process**: The script handles one GPU device per MPI rank.
|
|
Multi-GPU-per-rank configurations are untested.
|
|
|
|
- **GPU thread format**: Tested with rocgdb from ROCm 7.2. Earlier ROCm versions
|
|
use a different thread name format (`AMDGPU Thread X.Y (GPU, WG (...), WF (N))`);
|
|
the script includes a regex for this legacy format but it is untested.
|