Skip to content

[ROCm: XLA profiler] Use real HIP stream_id instead of HSA queue handle#46182

Open
cj401-amd wants to merge 1 commit into
openxla:mainfrom
ROCm:cj/rocprofiler-sdk-stream-id
Open

[ROCm: XLA profiler] Use real HIP stream_id instead of HSA queue handle#46182
cj401-amd wants to merge 1 commit into
openxla:mainfrom
ROCm:cj/rocprofiler-sdk-stream-id

Conversation

@cj401-amd

Copy link
Copy Markdown
Contributor

Summary

  • Fix stream_id tracking in the ROCm profiler to use real HIP stream handles
    instead of HSA queue handles (kernels) or kInvalidStreamId (memcpy — silently dropped)
  • Add HIP stream tracking via ROCPROFILER_CALLBACK_TRACING_HIP_STREAM callback
    with external correlation ID, matching the rocprofiler-sdk reference tool (tool.cpp)
  • Add dense stream remapping so trace viewer shows "Stream #0", "Stream CMake build support #1"
    instead of raw 64-bit pointer values

Motivation

The ROCm profiler had two stream-id bugs:

  1. Kernels used dispatch_info.queue_id.handle (HSA hardware queue) as stream_id — not the HIP stream the user created
  2. Memcpy events used kInvalidStreamId (UINT64_MAX), causing them to be silently dropped from the device timeline

Approach

Uses the SDK's purpose-built ROCPROFILER_CALLBACK_TRACING_HIP_STREAM kind:

  • A thread-local stream stack tracks the current HIP stream via push-on-enter / pop-on-exit callbacks
  • An external correlation ID request service snapshots the current stream into correlation_id.external.value for every KERNEL_DISPATCH and MEMORY_COPY record
  • KernelEvent() and MemcpyEvent() read the real stream from the external correlation
  • The HSA queue handle is preserved in a new queue_id field for debugging

Changed files

File Lines What
rocm_tracer.cc +97 −4 TLS stream stack, callbacks, InitProfiling setup, event handler fixes
rocm_tracer.h +2 hip_stream_ctx_ member
rocm_tracer_utils.h +2 queue_id field on RocmTracerEvent
rocm_collector.cc +21 Dense stream remapping in Export()

Test plan

  • Built with ROCm 7.2.4, gfx942 on rocm-jaxlib-v0.10.2
  • Ran jax_matmul.py (JIT bfloat16 matmul, 10 profiled iterations) — trace collected successfully
  • Verify in trace viewer: kernel events on clean "Stream #N" lanes, memcpy events visible on device timeline
  • Verify multi-stream workload produces separate timeline lanes

Fix stream_id tracking in the ROCm profiler so that GPU events are
assigned to the correct HIP stream lanes in the trace viewer, matching
the behavior of both the rocprofiler-sdk reference tool (tool.cpp) and
Kineto (PyTorch).

Previously, KernelEvent() used dispatch_info.queue_id.handle (an HSA
hardware queue handle) as stream_id, and MemcpyEvent() used
kInvalidStreamId (causing memcpy events to be silently dropped from the
device timeline). HSA queues and HIP streams are orthogonal — a stream
may use different queues over time, and a queue may be shared by
multiple streams.

The fix uses the rocprofiler-SDK's purpose-built HIP stream tracking:

1. A dedicated hip_stream_ctx_ with ROCPROFILER_CALLBACK_TRACING_HIP_STREAM
   maintains a thread-local stream stack (absl::InlinedVector<uint64_t, 4>):
   ROCPROFILER_HIP_STREAM_SET callbacks push/pop the current hipStream_t
   around every HIP API call. The context is process-lifetime (like
   utility_context_) so the TLS stack stays warm for the first dispatch
   after Enable().

2. An external correlation ID request service on the main tracing context
   snapshots tls_stream_stack.back() into correlation_id.external.value
   for every KERNEL_DISPATCH and MEMORY_COPY record.

3. KernelEvent() and MemcpyEvent() read rec.correlation_id.external.value
   to get the real HIP stream_id. The HSA queue handle is preserved in a
   new queue_id field on RocmTracerEvent for debugging.

4. PerDeviceCollector::Export() remaps raw stream handle values (64-bit
   pointers) to dense sequential indices (0, 1, 2, ...) so the trace
   viewer shows clean "Stream #0", "Stream #1" lane names.

Changes:
- rocm_tracer.cc: Add thread_local tls_stream_stack (InlinedVector),
  hip_stream_callback(), stream_external_correlation_callback() with
  defensive empty check. Create and start hip_stream_ctx_ in
  InitProfiling(), stop in toolFinalize(). Configure external
  correlation ID request service on context_ using std::size(kinds).
  KernelEvent(): stream_id = rec.correlation_id.external.value,
  queue_id = kinfo.queue_id.handle. MemcpyEvent(): stream_id =
  rec.correlation_id.external.value. Add VLOG for unexpected HIP
  stream operations. Add breadcrumb comments at consumption sites.
- rocm_tracer.h: Add rocprofiler_context_id_t hip_stream_ctx_ member.
- rocm_tracer_utils.h: Add uint64_t queue_id field to RocmTracerEvent.
- rocm_collector.cc: Add dense stream remapping in Export().
@cj401-amd
cj401-amd force-pushed the cj/rocprofiler-sdk-stream-id branch from 0a94bdf to f1b9c72 Compare July 24, 2026 19:21
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