Skip to content

test(hip-tests): add a dual-stream graph capture test - #14166

Merged
gandryey merged 3 commits into
developfrom
amd/dev/gandryey/graph_failure_test
Oct 27, 2026
Merged

gandryey merged 3 commits into
developfrom
amd/dev/gandryey/graph_failure_test

Conversation

@gandryey

@gandryey gandryey commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

New untested graph path

Technical Details

A graph captured from two streams with an event fork and join per layer can run a node before its producer on another hardware queue finishes when the runtime drops a cross-queue wait. Small graph tests don't catch this: their kernels finish before the other queue starts, and their graphs are too short to spread over several queues.

  • Capture 32 layers shaped like a dual-stream MoE layer: a three-kernel branch and a one-kernel branch run in parallel on the two streams and an add joins them, feeding the next layer.
  • Kernels spin so the branches overlap; every intermediate buffer is poisoned before each of 20 replays and the result is compared exactly with a host reference.
  • Two cases: the one-kernel branch on the side stream, and the three-kernel branch on the side stream

Issue Tracking

JIRA ID : ROCM-1667

Test Plan

It's the test

Test Result

Pass

Submission Checklist

N/A

A graph captured from two streams with an event fork and join per
layer can run a node before its producer on another hardware queue
finishes when the runtime drops a cross-queue wait. Small graph tests
don't catch this: their kernels finish before the other queue starts,
and their graphs are too short to spread over several queues.

- Capture 32 layers shaped like a dual-stream MoE layer: a three-kernel
  branch and a one-kernel branch run in parallel on the two streams and
  an add joins them, feeding the next layer.
- Kernels spin so the branches overlap; every intermediate buffer is
  poisoned before each of 20 replays and the result is compared exactly
  with a host reference.
- Two cases: the one-kernel branch on the side stream, and the
  three-kernel branch on the side stream.
Copilot AI balanced review requested due to automatic review settings October 23, 2026 16:34
@gandryey
gandryey requested review from a team as code owners October 23, 2026 16:34
@therock-pr-bot

therock-pr-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

✅ All Policy Checks Passed

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ⚠️ Warning Error: Source/code files changed without an accompanying unit test.
Expected: add at least one test file named like test_<name>.py / test_<name>.cpp (or <name>_test.*).
Current: code file(s) changed: projects/hip-tests/catch/unit/graph/hipGraphDualStreamCapture.cc; no test file found
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —

🎉 All policy checks passed!

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

Copy link
Copy Markdown

🚫 Please fix the failed policies before requesting reviews.

The following policy checks failed:

  • ❌ PR Description

The Not ready to Review label has been added to this PR.
Once all policies pass, the label will be removed automatically.

Copilot AI 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.

🟡 Changes recommended

The layer arithmetic can erase early corruption before final validation, allowing ordering failures to escape detection.

1 open issue
What changed in this PR

Adds regression coverage for cross-queue ordering in deep, dual-stream HIP graph captures.

Changes:

  • Adds two 32-layer graph tests with reversed branch placement and event-based fork/join dependencies.
  • Replays each graph 20 times with poisoned buffers and host-reference validation.
  • Registers both tests in the AMD build and level-2 graph test configuration.
File Description
projects/​hip-tests/​catch/​unit/​graph/​hipGraphDualStreamCapture.cc Implements dual-stream capture and replay tests.
projects/​hip-tests/​catch/​unit/​graph/​CMakeLists.txt Adds the test source to the AMD build.
projects/​hip-tests/​catch/​config/​configs/​unit/​graph.yaml Registers both cases as level-2 execution tests.

Review effort: Balanced

Each layer computed 146 * x + c. With an even multiplier the product
over 32 layers is 0 mod 2^32, so every element ended at the same value
and an even error in an early layer was erased by the later ones.

- Use 10 instead of 11 for the shared branch: the per-layer multiplier
  becomes 145, which is odd, so a wrong value in any layer still
  changes the final result.
The graph executor assigns queues per dependency level, not per
capture stream, so either branch can share a queue with the add. With
kernels that spun before reading their input, a consumer that started
early waited out its own spin and usually read finished data, so a
dropped wait was only caught for some placements.

- Every kernel reads its inputs first, then spins, then writes; the add
  spins too. A consumer that starts before its producer has finished
  reads poison wherever the branches run.
- Spin lengths are in microseconds, scaled by the device's wall clock
  rate.
- Check that the host reference doesn't collapse all elements to one
  value.
- Describe the two cases by capture order instead of by stream.

@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)

[SUGGESTION] Graph, events, streams and about 40 MB of device buffers leak when a REQUIRE fails

In RunDualStreamGraph, cleanup only happens at the end of the function. REQUIRE(expected[0] != expected[1]) and the per-replay REQUIRE(mismatches == 0) both run before that cleanup, as does every HIP_CHECK in CaptureLayers and the setup code. If any of them fails, Catch2 throws and nothing is released: graph_exec, graph, 64 events, 2 non-blocking streams, and 161 device buffers of 256 KiB each (about 40 MB). If a HIP_CHECK fails inside CaptureLayers between hipStreamBeginCapture and hipStreamEndCapture, the main stream also stays in global capture mode.

Suggested fix: Hold the resources in RAII wrappers or a scope guard so they are released when an exception unwinds: streams, events, buffers, graph and graph exec. A simpler option is to record the mismatch count, run cleanup, and only then REQUIRE. In CaptureLayers, end or abort the capture before propagating a failure, for example with a guard that calls hipStreamEndCapture and destroys any partial graph.

@gandryey
gandryey merged commit c131016 into develop Oct 27, 2026
248 of 253 checks passed
@gandryey
gandryey deleted the amd/dev/gandryey/graph_failure_test branch October 27, 2026 23:21
ywang103-amd pushed a commit that referenced this pull request Oct 28, 2026
## Motivation
New untested graph path

## Technical Details
A graph captured from two streams with an event fork and join per layer
can run a node before its producer on another hardware queue finishes
when the runtime drops a cross-queue wait. Small graph tests don't catch
this: their kernels finish before the other queue starts, and their
graphs are too short to spread over several queues.

- Capture 32 layers shaped like a dual-stream MoE layer: a three-kernel
branch and a one-kernel branch run in parallel on the two streams and an
add joins them, feeding the next layer.
- Kernels spin so the branches overlap; every intermediate buffer is
poisoned before each of 20 replays and the result is compared exactly
with a host reference.
- Two cases: the one-kernel branch on the side stream, and the
three-kernel branch on the side stream

## Issue Tracking
JIRA ID : ROCM-1667

## Test Plan
It's the test

## Test Result
Pass

## Submission Checklist
N/A
@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.

4 participants