Repository navigation
fix(rocprofiler-sdk): stop replay passes from consuming kernel iterations - #11335
Conversation
--kernel-iteration-range selects host-observed kernel launches. The filter advances a per-kernel counter every time it is consulted, and counter_dispatch_callback consulted it on every replay pass, so one launch was charged as many iterations as there were counter groups. With --replay-mode kernel and a range of [1], pass 0 matched iteration 1 and passes 1..N-1 were rejected, so their counter groups were never configured and were silently dropped: the run reported the first group only. Across launches the counter conflated launches with passes (10 after two launches of a five-group replay instead of 2), so any range beyond the first selected an arbitrary launch/pass pair. Consult the filter once per dispatch instead. Pass 0 asks, which advances the count by the single launch the application made, and the remaining passes of that dispatch reuse the answer. The decision is cleared when a replay loop begins so it cannot leak between dispatches. Non-replayed dispatches are unaffected. Adds an integration test running replay with --kernel-iteration-range and asserting every surviving dispatch still carries all of its passes. The combination was previously untested: the iteration-range tests never enable replay, and the replay tests never set a range. Co-authored-by: Vivek Kale <vivek.kale@amd.com>
✅ All Policy Checks Passed
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🚫 Please fix the failed policies before requesting reviews. The following policy checks failed:
The |
There was a problem hiding this comment.
🟢 Approval recommended
The dispatch-level caching approach aligns with the stated replay/pass execution model in this tool and the added integration test directly guards against the reported regression.
Pull request overview
This PR fixes an interaction bug between kernel replay and --kernel-iteration-range in the rocprofiler-sdk tool: the iteration-range filter was being consulted once per replay pass (instead of once per user-visible dispatch), causing a single kernel launch to consume multiple “iterations” and leading to later replay passes being silently dropped. It also adds an integration regression test to ensure filtered dispatches still include all replay passes.
Changes:
- Cache the kernel-iteration-range targeting decision per dispatch during kernel replay so only replay pass 0 advances the per-kernel iteration counter.
- Reset the cached decision at the start of each replay loop to prevent cross-dispatch leakage.
- Add an integration test covering
--replay-mode kernelcombined with--kernel-iteration-range, validating pass completeness.
File summaries
| File | Description |
|---|---|
| projects/rocprofiler-sdk/source/lib/rocprofiler-sdk-tool/tool.cpp | Ensures kernel-iteration-range filtering is applied once per dispatch (not per replay pass) by caching the decision in a thread-local during replay. |
| projects/rocprofiler-sdk/tests/rocprofv3/kernel-replay/CMakeLists.txt | Adds an integration regression test combining kernel replay with --kernel-iteration-range and validating that surviving dispatches still have all replay passes. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Mirror AIPROFSDK-1130 with four launches, iteration range 2-3, and two counter groups. Assert that exactly two logical dispatches survive and that each carries both replay passes with distinct counter groups. This covers rejected and accepted decisions, resetting between dispatches, and pass completeness without pinning numeric dispatch IDs. Co-authored-by: Cursor <cursoragent@cursor.com>
bgopesh
left a comment
There was a problem hiding this comment.
Claude flags the position of the fix. worth looking
Thanks for that. Working on fixing and then testing again. |
…geted_kernel Review feedback: the replay/iteration conflation is a property of the filter being stateful, not of the counter callback, so guarding a single caller left the invariant enforced by that call site's local convention rather than by the function owning the state. is_targeted_kernel() is the shared chokepoint for four callers: att_dispatch_callback, att_dispatch_consecutive_kernel_callback, counter_dispatch_callback and spm_dispatch_callback. Only the third was guarded. Replay does not drive the other three today -- rocprofv3 rejects ATT, PC sampling and SPM alongside --replay-mode kernel -- so there was no live bug, but any path that later gained replay would have silently reacquired the original one. Move the memoization into is_targeted_kernel() so the rule travels with the state it protects. counter_dispatch_callback returns to its original form and the behavioural change is now five lines in one function. No functional change to the fix: pass 0 still consults the filter and advances the count by the single launch the application made, later passes of that dispatch still reuse the answer, the cache is still cleared when a replay loop begins, and non-replayed dispatches still take the unchanged path. Co-authored-by: Vivek Kale <vivek.kale@amd.com>
|
This pull request has been inactive for 25 days and will be marked as stale. If you would like to keep this PR open, please:
This PR will be automatically closed in 5 days if no further activity occurs. |
|
@bgopesh can you please re-review? |
The checks on this branch last ran on Sep 9, against a develop that has moved on since, and the required "RCCL PR gate" check was added to the develop ruleset after that run, so it has never been reported here. This commit changes no files; it only starts a fresh CI run.
Both are outputs of the same kernel-replay run, so the option reads better beside --json-input than at the end of pytest_addoption. It also keeps this change clear of the option that the kernel-iteration-range fix (#11335) appends after --common-counters, so the two PRs merge in either order without a conflict in conftest.py.
rocprofv3-test-kernel-replay-iteration-range-generate arrived on develop with #11335 after the other generate tests got RUN_SERIAL. Its validate step compares SQ_WAVES and SQ_INSTS_VALU across passes as well, so it needs to run alone for the same reason. JIRA ID: AIPROFSDK-1171 Co-authored-by: Vivek Kale <vivek.kale@amd.com>
TheRock Submodule Bump ActivityNewest first
|
…ions (#11335) --kernel-iteration-range numbers the launches the application made. Kernel replay runs one launch once per counter group, and every pass consulted the stateful iteration filter, so one launch was counted once per pass. Passes past the end of the range were rejected and those counter groups were dropped. The run still exited successfully, with records that looked complete. is_targeted_kernel() now decides once per logical dispatch: pass 0 consults the filter and later passes reuse that answer. Each replay loop clears the cached decision when it starts. A dispatch that is not replayed still consults the filter every time. The regression test is the reported case, AIPROFSDK-1130: four launches, range 2-3, two counter groups. It requires exactly two selected dispatches, each with passes [0, 1], and does not pin dispatch ids. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…CHANGELOG Record the #11335 kernel-replay --kernel-iteration-range / multi-group --pmc fix under Unreleased Resolved issues for ROCm 10.2.
Drop the remove-callbacks / set_agents / #11335 Unreleased bullets from this PR so they land via the dedicated docs PR instead of conflicting here.
Resolve the CHANGELOG conflict by keeping the rocprofv3 --doctor (#12889) and hsa_amd_queue_create (#13720) entries from develop alongside this PR's Unreleased entries. Replace the queue-interposition, SPM agent-scoping, and kernel replay iteration-range entries with more detailed versions (#11967-#11970, #11335). Co-Authored-By: Claude <noreply@anthropic.com>



Motivation
--kernel-iteration-rangeselects application-observed kernel launches. Kernel replay createsmultiple executions of one logical dispatch so profiling can collect a different group on each
pass. Before this fix,
counter_dispatch_callbackconsulted the stateful iteration filter on everypass. The filter therefore mistook replay passes for new application iterations.
The validation report reproduced this with independent HIP and Kokkos workloads. Both the
application and
rocprofv3exited successfully, with no warning, even though the resulting counterrecords were incomplete and appeared valid.
For example, with iteration range
2-3and two replay passes, the expected output is two selectedlogical dispatches, each containing passes
[0, 1]: four counter records in total. Instead, thefilter counted each pass as an iteration. Pass 1 from one logical dispatch and pass 0 from the next
were selected separately, leaving both dispatches incomplete. Numeric dispatch IDs may vary; the
missing pass in each dispatch is the failure.
Intuition: one dispatch, several physical executions
Profiling hardware cannot always measure every requested event simultaneously, so tools divide the
request into groups and execute the same dispatch once per group. That creates two different units:
iteration ranges describe this unit.
and per-pass configuration describe this unit.
The bug came from applying a logical-dispatch filter at the replay-pass boundary.
flowchart TB subgraph beforeFix [Before: filter evaluated per replay pass] launch1Before["Logical launch 1"] launch1Pass0["Pass 0 calls filter; iteration 1; rejected"] launch1Pass1["Pass 1 calls filter; iteration 2; selected"] incomplete1["Dispatch D1 contains pass 1 only"] launch2Before["Logical launch 2"] launch2Pass0["Pass 0 calls filter; iteration 3; selected"] launch2Pass1["Pass 1 calls filter; iteration 4; rejected"] incomplete2["Dispatch D2 contains pass 0 only"] launch1Before --> launch1Pass0 --> launch1Pass1 --> incomplete1 launch2Before --> launch2Pass0 --> launch2Pass1 --> incomplete2 end subgraph afterFix [After: filter evaluated per logical dispatch] launch1After["Logical launch 1; filter iteration 1; rejected"] launch2After["Logical launch 2; filter iteration 2; selected"] launch2Passes["Passes 0 and 1 reuse selected"] complete2["Dispatch D2 contains passes 0 and 1"] launch3After["Logical launch 3; filter iteration 3; selected"] launch3Passes["Passes 0 and 1 reuse selected"] complete3["Dispatch D3 contains passes 0 and 1"] launch1After --> launch2After --> launch2Passes --> complete2 launch2After --> launch3After --> launch3Passes --> complete3 endExpected record shape after the fix:
Code map:
tool.cppL391-L409.tool.cppL1641-L1657.tool.cppL2023-L2036.authoritative pass index:
tool.cppL2561-L2593.Technical Details
The iteration-range decision now belongs to the dispatch:
tl_replay_dispatch_targeted, preventing the previous dispatch's decisionfrom leaking into the next replay loop.
is_targeted_kernel(), advancing the per-kernel iteration count exactly once, andcaches the result.
Replay PASS callbacks and the counter dispatch callback execute synchronously and in order on the
enqueuing thread, so the decision can be stored thread-locally without a process-wide map or lock.
Issue Tracking
JIRA ID: AIPROFSDK-1130
Test Plan
Adds an integration test combining kernel replay with
--kernel-iteration-range. It selects asubset of logical launches and verifies that every selected dispatch still contains every expected
replay pass. This combination was previously uncovered: iteration-range tests did not enable
replay, while replay tests did not specify an iteration range.
The regression test mirrors AIPROFSDK-1130 with four launches, range
2-3, and two counter groups.It asserts exactly two selected logical dispatches, passes
[0,1]on each, and a distinct countergroup on each pass. Numeric dispatch IDs are deliberately not pinned.
Regression coverage:
CMakeLists.txtL148-L202.Test Result
CI restarted for the latest test-only update. As of September 8, 2026: 8 passed, 29 pending,
0 failed, and 8 skipped.
View the live CI status.
Submission Checklist
https://github.com/ROCm/rocm-systems/blob/develop/CONTRIBUTING.md.