feat: HIP CLR profiler integration (hipProfiler*Ext v0.1.0) - #85
feat: HIP CLR profiler integration (hipProfiler*Ext v0.1.0)#85sunway513 wants to merge 9 commits into
Conversation
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 Environment
Test 1 — HSA default mode regressionResult: PASS
Confirms the schema change and writer binding are working end-to-end on HSA mode. No regression. Test 2 — HIP mode graceful fallbackResult: PASS
This is the exact graceful-fallback behavior the RFC promised. Test 3 — Schema migration on pre-existing trace fileCreated an Result: PASS
Summary
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. |
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).
acbb17f to
0f0f5fe
Compare
🤖 GPT-5.4 Code ReviewNEEDS CHANGES Real issues1. Dependency violation / project policy risk
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
|
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).
🤖 GPT-5.4 Code ReviewMINOR ISSUES Correctness
Security / Robustness
Dependency violations
Performance
Style / consistency
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.
🤖 GPT-5.4 Code ReviewNEEDS CHANGES Real issues1. Correctness:
|
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
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:What's in this PR
Core:
src/hip_intercept.cpphipProfilerEnableExt/hipProfilerDisableExt/hipProfilerGetRecordsExtDocker:
docker/Dockerfile.hip-profilerFull reproducible build environment:
rocm/ufb-private:pytorch-2.10.0-rocm7.13.0a20260424(ROCm 7.13 nightly)ROCm/rocm-systemsbranchamd/dev/gandryey/ROCM-1667-12(PR #5215)libamdhip64.sowith profiler extensions from sourcerocm/pytorch-private:rtl-hip-profiler-v013_20260427Build script:
docker/build-hip-profiler.shOne-command image rebuild when CLR branch or ROCm base updates.
Validation
v0.1.0 API (ROCm 7.13 + new CLR, MI355X)
New fields verified:
Kernel names now fully demangled:
v0 API backward compat (ROCm 7.2 + old CLR, MI355X)
CPU tests: 216 passed, 34 skipped
Quick start
Dependencies
Test plan
Generated with Claude Code