Skip to content

feat: HIP CLR profiler integration (hipProfiler*Ext v0.1.0) - #85

Open
sunway513 wants to merge 9 commits into
mainfrom
feat/hip-profiling-mode
Open

feat: HIP CLR profiler integration (hipProfiler*Ext v0.1.0)#85
sunway513 wants to merge 9 commits into
mainfrom
feat/hip-profiling-mode

Conversation

@sunway513

@sunway513 sunway513 commented Apr 10, 2026

Copy link
Copy Markdown
Owner

Summary

Integrate German's HIP CLR built-in profiler API (hipProfiler*Ext) as an alternative profiling path for RTL. This uses the CLR's internal dispatch table wrappers instead of HSA signal injection, providing:

  • Multi-process safe profiling (no shared HSA signal pool contention)
  • CUDAGraph compatible (no signal injection into graph replay packets)
  • Zero overhead on production workloads (CLR callback path, no AQL packet modification)

What's in this PR

Core: src/hip_intercept.cpp

  • Consumes CLR profiler records via hipProfilerEnableExt / hipProfilerDisableExt / hipProfilerGetRecordsExt
  • Backward compatible: auto-detects v0 (has Reset) vs v0.1.0 (no Reset) API at runtime
  • v0.1.0 new fields consumed:
    • Grid/block dimensions for kernel dispatches -> stored in API args
    • Memory addresses for alloc/copy ops (memory1/memory2/size)
    • Demangled kernel names
    • Linked-list traversal for multi-op graph launches
  • v0 fallback: contiguous array traversal, optional Reset call

Docker: docker/Dockerfile.hip-profiler

Full reproducible build environment:

  • Base: rocm/ufb-private:pytorch-2.10.0-rocm7.13.0a20260424 (ROCm 7.13 nightly)
  • CLR source: ROCm/rocm-systems branch amd/dev/gandryey/ROCM-1667-12 (PR #5215)
  • Builds libamdhip64.so with profiler extensions from source
  • Patches applied: version map exports, nodiscard warning fixes
  • Pre-built image: rocm/pytorch-private:rtl-hip-profiler-v013_20260427

Build script: docker/build-hip-profiler.sh

One-command image rebuild when CLR branch or ROCm base updates.

Validation

v0.1.0 API (ROCm 7.13 + new CLR, MI355X)

rtl[hip]: hipProfiler*Ext API v0.1.0 resolved, Enable returned 0 (start_id=4159)
rtl[hip]: draining 4159 records (1 chunks x 10000)
rtl[hip]: drained api=4159 kernel=12 copy=2 barrier=0 graph_ops=0 skipped=0

New fields verified:

hipMalloc: ptr=0x721007c00000 size=2097152
hipLaunchKernel: grid=[1024,1,1] block=[256,1,1]
hipMemcpyWithStream: dst=0x14e82bc0 src=0x721004300000 size=262144

Kernel names now fully demangled:

Cijk_Ailk_Bljk_S_B_Bias_HA_S_SAV_UserArgs_MT32x32x128_MI16x16x1_SN_LDSB1_AFC0_AG...

v0 API backward compat (ROCm 7.2 + old CLR, MI355X)

rtl[hip]: hipProfiler*Ext API v0 resolved, Enable returned 0 (start_id=0)
rtl[hip]: draining 3306 records (1 chunks x 10000)
rtl[hip]: drained api=3306 kernel=11 copy=1 barrier=0 graph_ops=0 skipped=0

CPU tests: 216 passed, 34 skipped

Quick start

# Pull pre-built image
docker pull rocm/pytorch-private:rtl-hip-profiler-v013_20260427

# Run with hip profiler mode
docker run --device=/dev/kfd --device=/dev/dri --group-add video \
  --security-opt seccomp=unconfined --cap-add SYS_PTRACE --privileged \
  --network host --ipc host -e HIP_VISIBLE_DEVICES=0 \
  rocm/pytorch-private:rtl-hip-profiler-v013_20260427 \
  bash -c "GPU_CLR_PROFILE_OUTPUT=/dev/null rtl trace --mode hip -o /tmp/trace.db -- \
    python3 -c 'import torch; x=torch.randn(512,512,device=\"cuda\"); torch.mm(x,x); torch.cuda.synchronize()'"

Dependencies

Test plan

  • v0.1.0 API E2E on MI355X (demangled names, grid dims, memory addrs)
  • v0 API backward compatibility on MI355X
  • CPU unit tests (216 passed)
  • Multi-GPU test with ATOM serving
  • Overhead benchmark vs baseline

Generated with Claude Code

@sunway513

Copy link
Copy Markdown
Owner Author

GPU smoke tests on banff MI300X (ROCm 7.2.0)

Ran the three pieces of GPU-side validation that can be verified without a ROCm build containing the CLR profiler patch. The branch was cloned fresh, built on banff against ROCm 7.2, and run against the tests/gpu_workload gemm HIP binary.

Environment

  • Host: banff-ccs-aus-p20-14, 8x MI300X
  • ROCm: 7.2.0 (libamdhip64.so.7.2.70201)
  • CLR profiler symbols present: 0 (confirmed via nm -D libamdhip64.so | grep hipClrProfiler)
  • Load avg: 0.35, no other GPU users

Test 1 — HSA default mode regression

HSA_TOOLS_LIB=$(pwd)/librtl.so RTL_OUTPUT=trace_hsa.db ./tests/gpu_workload gemm 256 10

Result: PASS

  • 13 intercept calls, 12 kernels injected, 12 recorded OK, 0 drops
  • rocpd_op has the new correlation_id column with DEFAULT 0
  • SELECT count(*), min(correlation_id), max(correlation_id) FROM rocpd_op12, 1, 12 — the counter-based correlation_id is now being persisted (previously silently dropped)
  • top view returns correct data: matmul 10 calls 372.0us total 98.79%, __amd_rocclr_fillBufferAligned 2 calls

Confirms the schema change and writer binding are working end-to-end on HSA mode. No regression.

Test 2 — HIP mode graceful fallback

HSA_TOOLS_LIB=$(pwd)/librtl.so RTL_MODE=hip GPU_CLR_PROFILE=/dev/null   RTL_OUTPUT=trace_hip.db ./tests/gpu_workload gemm 256 10

Result: PASS

rtl: mode=hip
rtl[hip]: GPU_CLR_PROFILE=/dev/null
rtl[hip]: skipping HSA queue intercept; CLR profiler handles capture
[... workload runs ...]
rtl[hip]: hipClrProfiler API not available in this ROCm build
rtl[hip]:   enable=(nil) disable=(nil) get_records=(nil) reset=(nil)
rtl[hip]: requires ROCm build with rocm-systems commit 5dc10a8 or later
rtl: trace finalized (0 records written)
  • Mode parsed correctly, HSA interception skipped
  • libamdhip64.so loaded via RTLD_NOLOAD
  • All 5 hipClrProfiler* symbols dlsym'd to (nil) cleanly — no crash
  • Warning printed with actionable remediation guidance
  • Workload itself ran successfully (GEMM 256x256 x10 done, exit 0). RTL does not break applications when the profiler API is absent.
  • Trace DB opened and closed cleanly with 0 records — expected since CLR profiler never activated

This is the exact graceful-fallback behavior the RFC promised.

Test 3 — Schema migration on pre-existing trace file

Created an old.db with the pre-change schema (no correlation_id column), then ran a HIP workload with RTL_OUTPUT=old.db to force schema migration on open.

Result: PASS

  • Pre-migration: rocpd_op has 9 columns, no correlation_id
  • Post-migration: rocpd_op has 10 columns with correlation_id INTEGER DEFAULT 0 appended. rocpd_api also migrated.
  • Pre-existing row preserved (id=1, correlation_id=0) — no data loss
  • 5 new rows written with correlation_id > 0 — new writes populate the column correctly
  • ALTER TABLE ADD COLUMN migration is idempotent (re-running produces no errors since we swallow them)

Summary

Test Platform Status
HSA mode regression + schema persistence MI300X ROCm 7.2 PASS
HIP mode graceful fallback (no CLR patch) MI300X ROCm 7.2 PASS
Schema migration on pre-existing DB MI300X ROCm 7.2 PASS
HIP mode with real CLR profiler BLOCKED on ROCm build with rocm-systems@5dc10a8+
Launch latency validation (Tests 1-4 from RFC) BLOCKED on same build
vLLM / ATOM end-to-end overhead BLOCKED on same build

The blocked items all need a ROCm build with German's CLR profiler patch. Once that build is available on one of our nodes, the remaining validation can happen quickly — the integration code itself is exercised and working.

Test plan checklist updated accordingly.

sunway513 and others added 5 commits April 11, 2026 05:14
Implements the design from RFC-002 (#84). Adds a new profiling mode
that uses the HIP CLR built-in profiler API from
ROCm/rocm-systems@5dc10a8 instead of HSA signal injection.

Benefits over HSA modes:
- Multi-process safe (no 0x1009 in ATOM/vLLM subprocess spawn)
- CUDAGraph native (CLR profiler handles graph nodes, no batch skip)
- HIP API CPU timeline (first time RTL can measure launch latency)
- SDMA copy tracking with byte counts
- Demangled kernel names native from HIP runtime (no symbol iteration)

Add correlation_id column to rocpd_op and rocpd_api (default 0,
backward compatible). Add indexes on correlation_id. Migration via
ALTER TABLE ADD COLUMN for pre-existing trace files; ignored errors
make it idempotent. Prepared statements now bind correlation_id;
record_hip_api / record_kernel / record_copy / record_roctx all
persist the parameter that was previously silently dropped.

Add RtlMode::HIP enum value. Parse "hip" from RTL_MODE env var. When
mode is HIP, OnLoad() skips queue intercept setup / signal pool / worker
thread, registers shutdown handler, and returns. shutdown() branches
early for HIP mode and calls hip_intercept::hip_profiler_drain().
Teardown-order invariant (worker.join() before DB close) preserved
for HSA modes — HIP branch does not explicitly close the DB, relying
on the existing lazy_init atexit handler in trace_db.cpp.

Rewrite from placeholder to actual implementation. Declare the
HipClrApiRecord / HipClrGpuActivity types locally (upstream header
not yet shipped). dlopen libamdhip64.so with RTLD_NOLOAD (so we don't
force-load HIP when the app never used it), try multiple .so name
variants for ROCm 6 / 7 / symlink cases. dlsym the 5 hipClrProfiler*
functions. Drain sequence: Disable() -> GetRecords() -> iterate into
trace_db -> Reset(). Graceful fallback when symbols are missing.
Maps dispatch/copy/barrier op codes to record_kernel / record_copy.

Add "hip" to --mode choices. When mode=hip, cmd_trace sets
GPU_CLR_PROFILE=/dev/null in subprocess env. This lets the CLR
profiler self-activate during hip::init() (librtl.so can't call
hipClrProfilerEnable() from its OnLoad because HIP is mid-init at
that point). /dev/null suppresses the profiler's own JSON autosave;
rtl extracts records via GetRecords() and writes SQLite itself.

- make -j: clean build, no new dependencies (dl already linked)
- make test-cpu: 216 passed, 34 skipped, 0 failed
- test_source_guard still green (no roctracer/rocprofiler leaks)
- Existing HSA mode behavior unchanged

GPU validation on MI300X with a ROCm build that includes the CLR
profiler patch is tracked separately and gated by the validation
protocol from RFC-002 section "Kernel launch latency analysis".

Refs #79, #84
- GPU_CLR_PROFILE=1 (not /dev/null) to match HipClrProfilerInit check
- dlsym kHipClrApiNames[] + kHipClrApiNamesCount for per-API labeling
  (510 HIP API names instead of generic "HipApi" fallback)
- Update activation flow comments to reflect actual dispatch table
  wrapper + activity callback architecture

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Major ABI update to match hip_profiler_ext.h from branch
amd/dev/gandryey/ROCM-1667-12 (commit 6025cd1):

- HipClrApiRecord -> HipApiRecordExt (fixed 256 bytes)
- HipClrGpuActivity -> HipGpuActivityExt (fixed 128 bytes, bitfields)
- hipClrProfiler* -> hipProfiler*Ext (with fallback to old names)
- api_name is now a direct const char* pointer (no dlsym name table)
- Graph support: gpu_op_count + gpu_ops array for multi-op launches
- is_graph bitfield for graph-launched ops
- hipStream_t available per record
- Symbol probe tries *Ext names first, falls back to hipClrProfiler*

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Update to German's latest API (commit 8e637b7):

- GetRecords now returns 2D chunked array (zero-copy from CLR internals):
  hipProfilerGetRecordsExt(chunks, chunk_count, chunk_size, total_count)
  Chunks are 10000 records each, up to 1024 chunks (10M records max).
- HipCopyKindExt enum (13 values) encodes SDMA copy direction:
  H2D/D2H/D2D/Fill/BufToImage/ImageToBuf with rect/image variants.
  4-bit bitfield in HipGpuActivityExt replaces previous reserved bits.
- record_copy() now uses copy_kind for proper src/dst device assignment
  instead of defaulting to device_id/-1.
- Barrier ops tracked separately in drain diagnostics.
- Drop legacy hipClrProfiler* symbol fallback (API has evolved too far
  from initial 5dc10a8 struct layout to be compatible).

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Three critical fixes for HIP CLR profiler mode based on German's
ROCM-1667-12 implementation:

1. Call hipProfilerEnableExt() during probe to activate recording
   (GPU_CLR_PROFILE_OUTPUT alone only initializes, doesn't enable)

2. Use gpu_op_count instead of has_gpu_activity flag to detect GPU ops
   (CLR profiler never sets has_gpu_activity, uses op count instead)

3. Update env var from GPU_CLR_PROFILE to GPU_CLR_PROFILE_OUTPUT
   (matches German's latest hip::init() activation path)

Also adds rtl_hip profiler config to overhead_bench.py with LD_PRELOAD
pattern for custom libamdhip64.so + HSA stubs.

Validated: 48/48 E2E tests PASS on MI355X, overhead +0.3% on production
workloads (same as default HSA mode).
@sunway513
sunway513 force-pushed the feat/hip-profiling-mode branch from acbb17f to 0f0f5fe Compare April 11, 2026 05:14
@github-actions

Copy link
Copy Markdown

🤖 GPT-5.4 Code Review

NEEDS CHANGES

Real issues

1. Dependency violation / project policy risk

benchmarks/overhead_bench.py adds "rtl_hip" mode that hard-requires a custom-built libamdhip64.so from rocm-systems branch and documents profiler-extension symbols from that branch.

  • This is not a direct roctracer / rocprofiler-sdk / libroctx64 dependency, so it does not violate item (1) literally.
  • But it does introduce a nonstandard ROCm runtime dependency outside stock ROCm, which is a significant portability/regression risk for a “self-contained” profiler.

If this mode is intended to stay, it should be clearly gated as experimental and not treated as a normal benchmark option.


2. Incorrect / unsafe LD_PRELOAD handling in benchmark launcher

In _run_rtl_hip():

preload = hip_lib
if os.path.isfile(stubs_lib):
    preload = f"{stubs_lib} {hip_lib}"
env["LD_PRELOAD"] = preload

LD_PRELOAD is not consistently parsed as a space-separated list by the dynamic loader across environments; the portable separator is : for library search paths, but LD_PRELOAD itself is typically whitespace-separated by glibc. More importantly, this overwrites any existing LD_PRELOAD, unlike cmd_trace.py which preserves it.

Why this matters:

  • Can silently break existing preload-based tooling.
  • Inconsistent behavior between CLI path and benchmark path.

At minimum, preserve existing LD_PRELOAD and use one consistent construction strategy across both codepaths.


3. Potential underflow / OOB iteration in HIP drain

In hip_profiler_drain():

size_t remaining = total_count - c * chunk_size;
size_t n = (remaining < chunk_size) ? remaining : chunk_size;

If chunk_count * chunk_size > total_count, then for some c, c * chunk_size exceeds total_count and remaining underflows (size_t), causing a huge n and out-of-bounds reads.

Even if the producer API “should” be consistent, this is still a correctness/security bug on unchecked external data.

Use a guarded form, e.g.:

  • break when c * chunk_size >= total_count, or
  • compute base = c * chunk_size; if (base >= total_count) break;

4. Truncation of thread IDs

In hip_intercept.cpp:

db.record_hip_api(..., (int)rec.thread_id);

thread_id is declared as uint64_t and comments say it is a hash of std::thread::id. Truncating to int will collide badly on busy multi-threaded workloads.

This is a correctness issue for correlation/debugging. If DB schema only supports 32-bit TID semantics, this path should map/hash explicitly and document it; otherwise store full 64-bit.


5. Shutdown path may skip DB flush/close in HIP mode

shutdown() in hsa_intercept.cpp returns early for HIP mode after hip_profiler_drain() and relies on a separate atexit from lazy_init_db():

// trace_db flush/close is handled by the atexit handler registered during lazy_init_db()

That assumption is fragile:

  • If hip_profiler_drain() never opens the DB (e.g. no records / early error), no DB atexit may be registered.
  • More importantly, atexit ordering depends on registration order. If DB atexit was registered during shutdown-time lazy init, it will run before/after other handlers depending on when registration occurs. This deserves explicit validation.

I’m not calling this definitely broken, but the current comment overstates safety. The shutdown ordering for HIP mode should be made explicit rather than relying on lazy registration during teardown.

Other notes

  • No direct references to roctracer, rocprofiler-sdk, or libroctx64 were introduced in the C++ path.
  • HSA usage change in OnLoad() looks reasonable: HIP mode now avoids queue interception entirely.
  • SQLite changes themselves look fine; adding correlation_id plus indexes is okay, and ignoring ALTER TABLE errors is acceptable for this migration pattern.

Recommended fixes before merge

  1. Fix the chunk iteration underflow in hip_profiler_drain().
  2. Preserve existing LD_PRELOAD in benchmark HIP mode and make preload handling consistent.
  3. Stop truncating 64-bit HIP thread IDs to int, or explicitly remap them safely.
  4. Tighten HIP shutdown/DB lifecycle so flush/close ordering is explicit, not implicit.

Model: gpt-5.4

Hip mode shutdown() called hip_profiler_drain() then returned early,
skipping the flush()/close() calls. This left all trace data stranded
in the SQLite WAL file, producing an empty final trace DB.

Add explicit flush/close before the early return. Update stale comment
that incorrectly claimed an atexit handler would handle DB closure.

Also add __has_include guard for hip_profiler_ext.h so builds against
German's CLR branch use the official header automatically.

Tested: 3327 HIP API + 13 GPU ops captured, Perfetto JSON generated,
216 CPU tests pass. Zero profiling overhead on MI355X (4K GEMM x500).
@github-actions

Copy link
Copy Markdown

🤖 GPT-5.4 Code Review

MINOR ISSUES

Correctness

  • Potential duplicate/late activation bug in HIP mode

    • In hip_profiler_probe(), g_fn_enable() is called unconditionally once symbols resolve.
    • hip_profiler_drain() then immediately calls g_fn_disable() and g_fn_get_records().
    • If the profiler was already activated earlier via GPU_CLR_PROFILE_OUTPUT during hip::init(), calling Enable again at shutdown is at best unnecessary and at worst could perturb profiler state or return an error depending on CLR semantics.
    • More importantly, if the app was not already activated, enabling only at shutdown is too late to capture prior activity, so the “belt-and-suspenders” comment is misleading.
    • Suggestion: probe should only resolve symbols; activation should not happen during drain unless there is a documented “enable-after-init still captures future records” use case.
  • Unchecked underflow in chunk iteration

    • In hip_profiler_drain():
      size_t remaining = total_count - c * chunk_size;
      If chunk_count * chunk_size metadata is inconsistent, this can underflow and cause out-of-bounds iteration.
    • Probably benign if CLR guarantees consistency, but this is still an unchecked trust boundary from an external library. Guard with:
      size_t base = c * chunk_size;
      if (base >= total_count) break;
  • Thread ID truncation

    • HipApiRecordExt::thread_id is uint64_t, but it is written as:
      (int)rec.thread_id
    • This can truncate on large values and break correlation/grouping. If the DB schema only supports 32-bit TIDs, this should be explicit/documented; otherwise use 64-bit consistently.

Security / Robustness

  • Hard-coded LD_PRELOAD replacement in benchmark helper

    • _run_rtl_hip() sets:
      env["LD_PRELOAD"] = preload
      unlike cmd_trace.py, which preserves existing preload entries.
    • This can silently drop required preload libraries in benchmark environments and change behavior unexpectedly.
    • Not a security bug per se, but a real robustness issue. It should append/prepend to existing LD_PRELOAD, not overwrite it.
  • Unchecked return from g_fn_reset()

    • hip_profiler_drain() ignores the return value of g_fn_reset().
    • Since shutdown behavior depends on clearing CLR state before its own finalizer runs, failures should at least be logged.

Dependency violations

  • No forbidden dependency introduced
    • No references to roctracer, rocprofiler-sdk, or libroctx64 in the new C++ path.
    • The benchmark list still includes "roctracer" as an external comparison target, but that is not a runtime/library dependency of rocm-trace-lite itself.

Performance

  • Mostly fine
    • The HIP path is shutdown-only and zero-copy over CLR chunks, so no obvious hot-path allocation issue in this diff.
    • No new lock contention or thread-per-dispatch issue introduced.

Style / consistency

  • Logging is a bit noisy but acceptable
    • New fprintf(stderr, ...) diagnostics are consistent with the rest of the file.
    • No substantive style issues worth blocking on.

Model: gpt-5.4

setup.py previously read from rocm_trace_lite/lib/librtl.so which could
be stale. Now checks repo-root librtl.so first (make output location).

Also adds .claude/ project instructions and /gpu-bench skill with
pre-flight checklist, RTL verification steps, and known issues from
extensive benchmarking sessions.
@github-actions

Copy link
Copy Markdown

🤖 GPT-5.4 Code Review

NEEDS CHANGES

Real issues

1. Correctness: hip_profiler_drain() can underflow and walk past returned chunks

In src/hip_intercept.cpp:

size_t remaining = total_count - c * chunk_size;
size_t n = (remaining < chunk_size) ? remaining : chunk_size;

If chunk_count * chunk_size > total_count (which is exactly the expected case for a partially filled last chunk, and could also happen for any extra capacity chunking), then for any c where c * chunk_size > total_count, remaining underflows (size_t) and n becomes chunk_size. That causes out-of-bounds reads from chunks[c][i].

This needs a guard, e.g. break when c * chunk_size >= total_count.


2. Correctness / signal handling: HIP mode does DB work from atexit after skipping normal HSA init path

HIP mode returns early from OnLoad() and only registers:

std::atexit(shutdown);

Then shutdown() in HIP mode does:

  • hip_intercept::hip_profiler_drain()
  • SQLite writes/flush/close

This is fragile because atexit ordering relative to HIP runtime / C++ static destructors in other DSOs is not guaranteed in a way you can rely on here. Your own comments acknowledge CLR finalizer/destructor behavior. If HIP/CLR teardown runs before this handler in some cases, dlsymed function pointers / internal buffers may no longer be valid.

Not necessarily always broken, but this is a real lifecycle risk introduced by the new mode.


3. Performance / correctness: unconditional fprintf(stderr, ...) on probe/drain path

hip_profiler_probe() and hip_profiler_drain() print multiple lines unconditionally, including success paths:

fprintf(stderr, "rtl[hip]: hipProfiler*Ext API resolved, Enable returned %d\n", rc);
fprintf(stderr, "rtl[hip]: draining %zu records ...\n", ...);
fprintf(stderr, "rtl[hip]: drained api=... \n", ...);

For a profiler library intended for low overhead and production use, unconditional stderr logging from every traced process is a real issue. It can perturb workloads, spam multi-process jobs, and break tools expecting clean stderr. Existing code already prints diagnostics at shutdown, but this adds more noisy paths.

At minimum gate behind an env/debug flag or keep only the final summary.


4. Security / robustness: unchecked return from g_fn_reset()

At end of hip_profiler_drain():

g_fn_reset();

Return value is ignored, unlike disable / get_records. Since comments rely on Reset() to prevent later CLR finalizer output, failure matters. This should be checked and logged.


Dependency violations

No new dependency on roctracer, rocprofiler-sdk, or libroctx64 in code paths added here.

(There are mentions of roctracer in docs/bench scripts, but not as a linked/runtime dependency for rocm-trace-lite itself.)

Notes

The SQLite schema migration changes look reasonable and use the existing single-writer pattern; I don’t see a new SQLite thread-safety violation in this diff.


Model: gpt-5.4

@sunway513
sunway513 marked this pull request as draft April 16, 2026 18:00
Align with German's updated hipProfiler*Ext API from ROCm/rocm-systems
PR #5215. Backward-compatible: auto-detects v0 vs v0.1.0 at runtime.

New API features consumed:
- Grid/block dimensions for kernel dispatches (args string)
- Memory addresses for alloc/copy ops (memory1/memory2/size)
- Demangled kernel names (when v0.1.0 CLR is present)
- Linked-list traversal for multi-op graph launches (replaces array)

API changes handled:
- Enable/Disable now accept uint64_t* output param (start/end record ID)
- Reset removed in v0.1.0 (probed and called only if present)
- Version detection via Reset symbol presence

Tested with v0 API on MI355X: 3306 API records + 12 GPU ops captured.
Adds docker/Dockerfile.hip-profiler that builds libamdhip64.so with
German's hipProfiler*Ext v0.1.0 API (ROCm/rocm-systems PR #5215) from
source using the ROCm 7.13 nightly base image.

Base: rocm/ufb-private:pytorch-2.10.0-rocm7.13.0a20260424
CLR branch: amd/dev/gandryey/ROCM-1667-12

Build patches applied:
- Export hipProfilerEnableExt/DisableExt/GetRecordsExt in hip_hcc.map.in
- Fix nodiscard warnings in hip_clr_dispatch_wrappers.cpp

Pre-built image pushed to:
  rocm/pytorch-private:rtl-hip-profiler-v013_20260427
@sunway513 sunway513 changed the title feat: implement RTL_MODE=hip (HIP CLR profiler integration) feat: HIP CLR profiler integration (hipProfiler*Ext v0.1.0) Apr 27, 2026
@sunway513
sunway513 marked this pull request as ready for review April 27, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant