Skip to content

host_build_graph: capture the outer GRAPH task in the dependency graph - #1908

Closed
ChaoWao wants to merge 1 commit into
hw-native-sys:mainfrom
ChaoWao:fix/capture-outer-graph-task-in-dependency-graph
Closed

host_build_graph: capture the outer GRAPH task in the dependency graph#1908
ChaoWao wants to merge 1 commit into
hw-native-sys:mainfrom
ChaoWao:fix/capture-outer-graph-task-in-dependency-graph

Conversation

@ChaoWao

@ChaoWao ChaoWao commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • dep_gen opens a task's entry in submit_task_common, but an outer GRAPH task is
    emitted by graph_submit_definition, which builds its slot directly and never goes
    through there — so no GRAPH task, and no edge touching one, reached deps.json
  • graph_submit_definition now opens an entry for the task it emits and instantiates
    compute_task_fanin with the annotating form, so the boundary edges attach to it
  • the DepGraphAnnotate that raises those edges moves to file scope and is shared with
    the ordinary path instead of being duplicated
  • what is captured is the boundary: an outer GRAPH task dispatches no kernel of its own
    and the sub-DAG it replays owns no ring slots, which the comment now states so the
    coverage claim is not over-read again

Before this, examples/a2a3/host_build_graph/qwen3_14b_decode described a 40-layer
decode by its handful of non-Graph tasks alone, while the capture point calls itself
"the sole source of truth for fanout".

Testing

tests/st/a2a3/host_build_graph/graph_execution with --enable-dep-gen, on a2a3sim,
before and after:

case before after
record_then_replay_2d 6 tasks / 8 edges 8 tasks / 10 edges
record_then_replay_mix_spmd no deps.json written 3 tasks / 0 edges

mix_spmd submits nothing but Graphs, so dep_gen had no task to open an entry for and
produced no file at all. The 2d case gains its two outer GRAPH tasks and the two edges
into them; its count of tasks whose three kernel ids are all invalid goes 1 → 3 — the
pre-existing dummy fence plus the two GRAPH tasks, which share that signature, so an
all-invalid triple marks "dispatches no kernel", not "is a Graph".

  • Simulation: tests/st/a2a3/host_build_graph on a2a3sim (9 passed, 7 skipped),
    tests/st/a5/host_build_graph on a5sim (5 passed)
  • cpput: 107/107
  • Hardware: qwen3_14b_decode on a2a3 under task-submit

Capture stays gated on dep_gen_host_graph_enabled(), whose weak fallback returns
false, so a normal run adds one call per GRAPH submit — the same call the ordinary path
already makes per task. Measured on qwen3-14b decode, twelve rounds after against six
before: graph_submit min 0.106 → 0.110 ms, while counters this does not touch move
−0.016 (arena_h2d) to +0.007 (graph_upload) over the same interval, and the sum of
the scope's minima is flat at 0.660 → 0.661 ms. Below the measurement floor on a shared
box.

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@ChaoWao, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2bed6d30-a4d6-4ce0-bb00-c0fb59e4d47f

📥 Commits

Reviewing files that changed from the base of the PR and between d1eb826 and 084a70b.

📒 Files selected for processing (2)
  • src/a2a3/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp
  • src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ChaoWao
ChaoWao force-pushed the fix/capture-outer-graph-task-in-dependency-graph branch from 06abcab to 084a70b Compare August 20, 2026 03:43
dep_gen opens a task's entry inside submit_task_common, and an outer GRAPH task is
emitted by graph_submit_definition, which builds its slot directly and never goes
through there. So no GRAPH task and no edge touching one reached deps.json: on
examples/a2a3/host_build_graph/qwen3_14b_decode a 40-layer decode was described by
its handful of non-Graph tasks alone, while the capture point calls itself "the
sole source of truth for fanout".

graph_submit_definition now opens an entry for the task it emits and instantiates
compute_task_fanin with the annotating form, so the boundary edges attach to it.
The DepGraphAnnotate that raises those edges moves to file scope and is shared with
the ordinary path rather than duplicated. An outer GRAPH task dispatches no kernel
of its own, so it records INVALID_KERNEL_ID in all three slots, and the sub-DAG it
replays owns no ring slots — what is captured is its boundary, which the comment
states so the coverage claim is not over-read again.

On tests/st/a2a3/host_build_graph/graph_execution with --enable-dep-gen, both cases
gain their Graph structure, and one of them gains an artifact it never produced:

  record_then_replay_2d       6 tasks /  8 edges  ->  8 tasks / 10 edges
  record_then_replay_mix_spmd no deps.json        ->  3 tasks /  0 edges

The mix_spmd case submits nothing but Graphs, so dep_gen had no task to open an entry
for and wrote no file at all. The 2d case gains its two outer GRAPH tasks and the two
edges into them. Its count of tasks whose three kernel ids are all invalid goes 1 -> 3:
the pre-existing dummy fence, plus the two GRAPH tasks, which share that signature —
so an all-invalid triple marks "dispatches no kernel", not "is a Graph".

Capture stays gated on dep_gen_host_graph_enabled(), whose weak fallback returns
false, so a normal run adds one call per GRAPH submit — the same call the ordinary
path already makes per task. Measured on qwen3-14b decode, twelve rounds after
against six before: graph_submit min 0.106 -> 0.110 ms, while counters this does
not touch move -0.016 (arena_h2d) to +0.007 (graph_upload) over the same interval,
and the sum of the scope's minima is flat at 0.660 -> 0.661 ms. Below the floor.
@ChaoWao

ChaoWao commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator Author

Closing in favour of #1911, which landed the same change 27 minutes later as a strict
superset: every line of this diff is in it, plus a regression assertion in
test_graph_execution.py that this PR did not have. Keeping both open would mean
maintaining the same 46 lines twice.

The measurement evidence from here is now on #1911 as a review comment — the before/after
deps.json counts for both cases (record_then_replay_2d 6/8 → 8/10, and
record_then_replay_mix_spmd from no file at all to 3/0), the note that
kernel_ids == [-1, -1, -1] marks "dispatches no kernel" rather than "is a Graph" (the 2d
case's dummy fence shares that triple), and that deps_viewer renders a Graph-only run as
0 nodes because it drops isolated ones.

One CI note that outlives this PR: this branch hit a single st-network1-onboard-a2a3
failure (examples/workers/l4/global_tload_mixed_l3 — remote worker →
finalize_native_run failed with code -100, then Worker.close(): teardown left resources un-reclaimed (leaked): 1 global comm domain), while #1911, #1905, #1907 and #1890 all
passed that job. The example submits no Graph and the capture is gated on
dep_gen_host_graph_enabled(), so this diff cannot reach that path — recorded here rather
than dropped, in case the lane fails again.

@ChaoWao ChaoWao closed this Aug 20, 2026
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