Skip to content

feat(hrr): refuse the calls replay cannot reproduce, by name - #10642

Merged
amd-hsivasun merged 77 commits into
developfrom
users/danielbolsson/hrr-scope-exclusions
Sep 30, 2026
Merged

amd-hsivasun merged 77 commits into
developfrom
users/danielbolsson/hrr-scope-exclusions

Conversation

@danielbolsson

Copy link
Copy Markdown
Contributor

AIRUNTIME-2705 · seventh of nine in the stack rooted at #10221 · base is #10641

What this changes

Some calls cannot be reproduced in a different process no matter how much of the argument is recorded. A host callback is a function pointer into the capturing process; a shareable handle names an export only its owner can make; a multi-device launch descriptor carries a host function address per device. Recording more bytes does not help — the missing thing is not in the arguments.

Until now these were handed to the real API anyway and failed somewhere inside the runtime, where the diagnosis is a bare HIP error code with no attribution, or they were quietly stubbed out. Twelve APIs become UNREPLAYABLE_PLAYBACK_APIS instead. The handler names itself and its reason on stderr, returns hipErrorNotSupported (fatal unless --continue-on-error), and is listed in the replay summary. Capture warns once at record time too, so the gap is visible when the recording is made rather than only when someone later tries to replay it, and the archive manifest carries the list.

A graph node that cannot be replayed marks its graph incomplete, so instantiation fails loudly rather than running a graph short a node.

The twelve

Reason APIs
Host callback hipLaunchHostFunc, hipLaunchHostFunc_spt, hipStreamAddCallback, hipStreamAddCallback_spt
Host node in a graph hipGraphAddHostNode, hipGraphHostNodeSetParams, hipGraphExecHostNodeSetParams
Cross-process handle import hipMemImportFromShareableHandle, hipMemPoolImportFromShareableHandle
Multi-device launch by host address hipLaunchCooperativeKernelMultiDevice, hipExtLaunchMultiKernelMultiDevice
Host-object destructor hipUserObjectCreate

hipMemPoolImportFromShareableHandle is the no-op #10641 deliberately left behind for this PR: its export side now genuinely mints an fd, so the recorded handle names something else here and faults inside the pool import.

Guardrails in the generator

An unreplayable API with a hand-written capture shim is refused, because that shim would skip the capture-time warning. So is one that appears in a second playback class, because only the first would take effect.

Reviewing this

Small and self-contained — 344 insertions across 11 files, and the whole PR is one idea. The expectations delta is the twelve rows moving to kHrrExpectUnreplayable.

Validation

Full HRR unit suite on gfx950, GPU 7: 86/86, both passes. gen_hrr_api_args.py regenerates to an empty diff.

Made with Cursor

danielbolsson and others added 15 commits September 17, 2026 07:25
…oads' into users/danielbolsson/hrr-scope-exclusions
…ix' into users/danielbolsson/hrr-api-payloads
…oads' into users/danielbolsson/hrr-scope-exclusions
Raw fprintf(stderr, ...) is not permitted in clr: it bypasses the
AMD_LOG_LEVEL machinery and writes unconditionally from inside a library
that other processes embed. mark_incomplete() is the last such call site
in this file, so it is routed through LogPrintfError from utils/debug.hpp,
which the file already includes. Error level rather than warning: once
this fires the archive is not faithful and replay must not treat it as
one. The trailing newline is dropped because amd::log_printf appends its
own.

The conversion was reverted on #10634 (cd4d649) so that PR's existing
approval stays valid. That revert is an ancestor of this branch, so
cascading it up the stack silently restored the raw fprintf here with no
conflict. This commit re-applies the conversion explicitly, so the fix
still reaches develop with this PR while #10634 keeps its approved shape.

The converted text is byte-identical to the form already carried by the
rest of the stack, which is what keeps the remaining merges conflict-free.

Signed-off-by: Daniel Olsson <Daniel.Olsson@amd.com>
The generated capture shim called note_unreplayable() before the real
call, but writes the event only when the call succeeds. A failed call
therefore listed the API under manifest.json's unreplayable_apis and
logged "The call is recorded" although nothing was recorded. Emit the
note next to write_event_raw() instead.

Also correct the PlaybackContext comment: unreplayable_apis and
reproduced_errors de-duplicate the per-API stderr lines; they are not
printed in the replay summary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@mangupta mangupta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI-assisted pre-review (for @mangupta)

danielbolsson and others added 11 commits September 25, 2026 07:49
…list

note_unreplayable() de-duplicated on the API name alone, so once an API was
listed for one reason every later, different reason (another truncated
argument, say) was dropped from both the warning and manifest.json. Key on
(api, reason) instead: each distinct pair warns once, and the manifest now
records the reasons as "unreplayable_apis": {"<api>": ["<reason>", ...]}.
Nothing reads the field yet, so the shape change breaks no consumer.

Both strings are written through metadata::json_escape(), now exported from
hip_capture_metadata.h, so a name or reason with a quote or backslash can no
longer produce a manifest.json that does not parse.

Host graph nodes: the unreplayable handler returns hipErrorNotSupported, so
by default replay stops at the call, not at instantiate. mark_graph_incomplete
stays because it is what makes instantiate refuse the graph under
--continue-on-error; the generator comment and DESIGN.md now say so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n/hrr-api-payloads

# Conflicts:
#	projects/clr/hipamd/src/hrr/hip_capture.cpp

Co-authored-by: Daniel Olsson <danielbolsson@users.noreply.github.com>
…oads' into users/danielbolsson/hrr-scope-exclusions

Co-authored-by: Daniel Olsson <danielbolsson@users.noreply.github.com>
…n/hrr-api-payloads

Co-authored-by: Daniel Olsson <danielbolsson@users.noreply.github.com>
…oads' into users/danielbolsson/hrr-scope-exclusions

Co-authored-by: Daniel Olsson <danielbolsson@users.noreply.github.com>
# Conflicts:
#	projects/hrr/tools/gen_hrr_api_args.py
Resolve conflicts from the #10641 squash merge by keeping this branch's
side: develop's copy of every conflicted file equals #10641's final head
(7039999), which this branch already contains.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@systems-assistant

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants