Skip to content

Add: support Graph Execution on A5 - #1733

Merged
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
zmnobug:feat/issue-1715-port-graph-execution-a5
Aug 10, 2026
Merged

Add: support Graph Execution on A5#1733
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
zmnobug:feat/issue-1715-port-graph-execution-a5

Conversation

@zmnobug

@zmnobug zmnobug commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Scope

This PR is intentionally a direct A5 port. It does not modify src/a2a3/ or extract Graph Execution into src/common/host_build_graph/.

The A5-specific differences are limited to the existing A5 runtime lifecycle/core topology and A5-native test kernels.

Follow-ups

Testing

  • Editable runtime build
  • Full non-hardware C++ unit suite: 92/92 effective (the sandbox-blocked socket case passed outside the sandbox)
  • A5 Host Build Graph simulation suite: 18 passed
  • A5 Graph Execution simulation: 3 passed
  • Pre-commit checks on all changed files
  • A5 onboard hardware CI

Fixes #1715

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 21a2f1f4-cadb-455c-8796-33a8ad949eb8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pull request ports host-build-graph Graph Execution to A5. It adds shared graph contracts, recording and replay, scheduler integration, host uploads, tests, documentation, and scheduler error code 104 handling.

Changes

Graph Execution runtime

Layer / File(s) Summary
Shared graph contracts and runtime shims
src/common/host_build_graph/*, src/a5/runtime/host_build_graph/runtime/*, src/a2a3/runtime/host_build_graph/runtime/*
Adds shared graph cache, wire-format, execution, materialization, and host-state interfaces. Architecture-specific headers now include the shared implementations.
Graph recording, replay, and host upload
src/a5/runtime/host_build_graph/orchestration/*, src/a5/runtime/host_build_graph/runtime/orchestrator_core/*, src/a5/runtime/host_build_graph/host/*
Adds graph lifecycle APIs, graph identity hashing, recording, serialized definitions, cache-hit replay, execution storage, and device upload handling.
Graph scheduler execution and completion
src/a5/runtime/host_build_graph/runtime/scheduler/*, src/a5/runtime/host_build_graph/runtime/shared/*
Adds graph preparation and ready queues, bounded materialization, dependency wake lists, activation gates, graph-node completion, and queue initialization.
Graph execution validation and documentation
src/common/host_build_graph/docs/*, tests/st/a5/host_build_graph/graph_execution/*, tests/ut/cpp/common/*
Adds architecture-neutral documentation, A5 graph orchestration scenes, record-and-replay tests, cache validation, reserved-field checks, and activation concurrency checks.
Scheduler error status and troubleshooting
src/*/runtime/host_build_graph/common/pto_runtime_status.h, src/common/runtime_status/error_names.h, docs/troubleshooting/device-error-codes/*
Adds scheduler error code 104, maps it to runtime name, description, and hint text, and documents its internal troubleshooting route.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

  • Issue 1706 — Tracks the host-build-graph Graph Execution design and scheduler work implemented here.
  • Issue 1716 — Covers related A5 scheduler overflow handling and error status changes.

Possibly related PRs

Poem

A rabbit records each graph in a neat little line,
Then replays every node when the tensors align.
Queues wake, gates open, and tasks hop through,
A5 now runs the graph path as A2A3 can too.
Overflow gets a number, a hint, and a name—
While tests guard the burrow against scheduler blame.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement the linked issue by porting shared Graph Execution infrastructure, A5 orchestration, scheduler support, diagnostics, documentation, and automated scene coverage.
Out of Scope Changes check ✅ Passed The documentation, diagnostics, shared runtime code, A5 implementation, and tests all support the linked Graph Execution port.
Title check ✅ Passed The title clearly identifies the main change: adding Graph Execution support to the A5 runtime.
Description check ✅ Passed The description directly explains the A5 Graph Execution port, scope, testing, and follow-up work.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h (1)

536-544: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

The doc comment contradicts the new parameter.

Lines 537-539 state that reset_for_reuse runs once per slot at init, and that whole-graph-resident hbg has no execution-time slot recycle. The new preserve_graph_binding parameter only has an effect if the function also runs during affine graph replay. Update the first sentence to name the second call site, so the two statements agree.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h` around lines
536 - 544, The documentation for reset_for_reuse must mention both
initialization and affine graph replay as call sites. Update the first sentence
of its comment to state that it runs once per slot at init and again during
affine graph replay, while preserving the remaining binding and scheduling
descriptions.
🧹 Nitpick comments (5)
src/common/host_build_graph/graph_execution.h (1)

300-317: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the paired cursor/total fields.

Four fields form near-identical name pairs: materialized_nodes / materialized_node_count, materialized_tensor_patches / materialized_tensor_patch_count, and the two GraphNodeStorage * members nodes / node_storage. The names do not state which member is the incremental cursor and which is the finalized total, or which pointer owns the allocation. graph_execution_materialize_slice advances these across calls, so a wrong pick silently truncates or re-materializes a slice.

Add a short comment on each pair that states its role. Keep the names, because renaming would touch graph_execution_impl.inc and both the a2a3 and a5 trees.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/common/host_build_graph/graph_execution.h` around lines 300 - 317, Add
concise comments beside the paired fields in the relevant state structure:
document that materialized_nodes and materialized_tensor_patches are incremental
cursors while their *_count counterparts are finalized totals, and clarify
whether nodes or node_storage owns the allocation. Preserve all existing field
names and behavior, including graph_execution_materialize_slice’s cross-call
updates.
src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h (1)

489-503: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Pin the slot size with a static_assert, and document that graph_context holds a device address.

Two points on the new fields.

The comment at Line 499 states that the graph metadata occupies the slot's tail padding. Nothing enforces that. PTO2TaskSlotState is copied into the shared-memory image and its size feeds the SM layout arithmetic and the prebuilt-arena offsets. If a later field pushes the struct past its current size, the layout shifts silently. Add a static_assert on sizeof(PTO2TaskSlotState) next to the struct so the padding claim fails at compile time instead of at runtime.

graph_context is a raw void * that relocate_host_orch_image in src/a5/runtime/host_build_graph/host/runtime_maker.cpp does not relocate. That is correct, because upload_graph_submissions writes an already-device pointer into it. State that at the field, so a future reader does not add it to the relocation walk and double-shift it.

📝 Proposed comment and assertion
     // Graph scheduling metadata occupies the slot's tail padding. Ordinary
     // ring tasks keep the index invalid and the context null.
+    // graph_context already holds a DEVICE address when set by
+    // upload_graph_submissions, so relocate_host_orch_image must not relocate it.
     int32_t graph_node_index{-1};
     void *graph_context{nullptr};

Add after the struct definition:

static_assert(sizeof(PTO2TaskSlotState) == 64 * /* current multiple */ 1,
              "PTO2TaskSlotState size feeds the SM layout; update the layout if it changes");

Apply the same change to the a2a3 copy in the same follow-up, to keep the two trees in parity.

Based on learnings: maintain byte-for-byte parity between src/a5/runtime/host_build_graph/ and src/a2a3/runtime/host_build_graph/ for corresponding files, and apply shared fixes to both trees in the same follow-up change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h` around lines
489 - 503, Pin the current sizeof(PTO2TaskSlotState) with a static_assert
immediately after the struct definition so changes to its tail padding fail
compilation and require layout updates. Update the graph_context field comment
to state that it stores an already-device-address pointer and must not be
relocated. Apply both changes to the corresponding a5 and a2a3 host_build_graph
copies, preserving byte-for-byte parity.

Source: Learnings

src/common/host_build_graph/graph_execution_impl.inc (1)

108-112: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Lock the assumption that storage_magic sits at offset 0.

Line 110 copies the first 8 bytes of the storage block and compares them to GRAPH_EXECUTION_STORAGE_MAGIC. This is correct only while storage_magic is the first member of GraphExecution and is 8 bytes wide. If a later change reorders the members, the reuse probe reads an unrelated field. The result is either a rejected reusable execution or a placement-new over live state.

Add a compile-time assertion next to this read.

🛡️ Proposed assertion
     auto *execution = reinterpret_cast<GraphExecution *>(static_cast<uintptr_t>(submission.execution_storage));
+    static_assert(offsetof(GraphExecution, storage_magic) == 0, "storage_magic must lead GraphExecution storage");
+    static_assert(sizeof(GraphExecution::storage_magic) == sizeof(uint64_t), "storage_magic must be 8 bytes");
     uint64_t observed_magic = 0;
     std::memcpy(&observed_magic, execution, sizeof(observed_magic));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/common/host_build_graph/graph_execution_impl.inc` around lines 108 - 112,
Add a compile-time assertion next to the observed_magic read in the reuse probe,
using GraphExecution and storage_magic to enforce that storage_magic remains at
offset 0 and retains the expected 8-byte width. Keep the existing memcpy and
reusable_execution_header_valid flow unchanged.
src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp (1)

411-417: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document why an external implicit producer edge is safe to drop.

Line 417 records a fanin only when producer_index >= 0. An implicit edge to a producer that predates the recording is discarded without marking the recording unsupported. The explicit-dependency path in graph_record_task at Lines 446-456 applies the opposite rule: a pre-recording dependency must be represented_by_boundary or the recording fails.

The drop is sound, but the reason is indirect. graph_classify_tensor must classify every node tensor. A tensor from an external producer matches no recorded node's packed range, so it must resolve to a boundary tensor or Line 481 marks the recording unsupported. The outer GRAPH task then rediscovers that producer through compute_task_fanin over the boundary inputs at Line 1496.

Add a short comment stating this invariant so a later change to the classification rules does not silently break it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp`
around lines 411 - 417, Add a concise comment immediately before the
producer_index filter in the fanin handling to document that pre-recording
implicit producers are safely dropped because graph_classify_tensor must
classify their tensors as boundary tensors, allowing the outer GRAPH task’s
compute_task_fanin path to rediscover the producer. Do not alter the existing
fanin or unsupported-recording logic.
src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h (1)

978-983: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Report the invalid graph-node state instead of dropping the completion.

Lines 979-983 return a default TaskCompletionOutcome when the execution pointer, the definition, the node array, or the node index is invalid. The node is not marked completed, drain_graph_wake_list does not run, and graph_execution_complete_node is not called. remaining_nodes then never reaches zero, the outer task never publishes, and every consumer of that node waits forever. The run stalls until the scheduler timeout latches PTO2_ERROR_SCHEDULER_TIMEOUT.

These states are unreachable in the current flow. graph_context and graph_node_index are set during materialization and survive affine replay, and execution->nodes is published before PREPARED. The concern is the failure mode, not the reachability.

The equivalent invalid-state checks added in scheduler_dispatch.cpp at Lines 1346-1358 latch PTO2_ERROR_INVALID_ARGS and stop the run. Make this path consistent so an invariant break produces a diagnostic rather than a hang. One option is to add an invalid flag to TaskCompletionOutcome and have the callers latch the scheduler error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h` around
lines 978 - 983, Update the completion path containing graph_execution_from_slot
to report invalid execution, definition, node-array, and node-index state
instead of returning a normal empty TaskCompletionOutcome. Propagate an invalid
outcome (or the existing equivalent) to its callers so they latch
PTO2_ERROR_INVALID_ARGS and stop the run consistently with
scheduler_dispatch.cpp, while preserving normal completion behavior for valid
state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/troubleshooting/device-error-codes.md`:
- Line 80: Update both runtime-status reference links around the
READY_QUEUE_OVERFLOW entry to point to the common pto_runtime_status.h path
under src/{arch}/runtime/host_build_graph/common, replacing the outdated
tensormap_and_ringbuffer references while preserving the existing table content.

In `@src/a2a3/runtime/host_build_graph/common/pto_runtime_status.h`:
- Line 41: Remove the stale PTO2_ERROR_READY_QUEUE_OVERFLOW definition and
retain the renamed SCHEDULER_ERROR_READY_QUEUE_OVERFLOW macro in
pto_runtime_status.h, ensuring scheduler and error-name mappings consistently
use the new symbol.

In `@src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h`:
- Line 515: Update the TaskKind::GRAPH branch in push_ready_routed to check the
boolean result of graph_ready_queue.push(slot_state); when insertion fails,
latch SCHEDULER_ERROR_READY_QUEUE_OVERFLOW using the same status-handling path
as non-graph queues, while preserving successful graph-task insertion behavior.

In `@src/a5/runtime/host_build_graph/host/runtime_maker.cpp`:
- Around line 508-516: Update GraphHostStateBinding in
src/a5/runtime/host_build_graph/host/runtime_maker.cpp:508-516 to delete copy
operations, add an explicit release() that clears graph_host_state, and invoke
it immediately after the upload around line 594 before relocation and H2D
copying; retain the destructor as an early-return backstop. Update the invariant
comment in src/a5/runtime/host_build_graph/runtime/pto_orchestrator.h:119-122 to
identify this explicit clearing point. Apply the identical changes to the
corresponding a2a3 host/runtime files, preserving byte-for-byte parity.

In
`@src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp`:
- Around line 1460-1498: In graph_submit_definition, handle the
compute_task_fanin failure path by resetting the newly allocated slot’s
task_kind from TaskKind::GRAPH to the appropriate non-graph/invalid state before
returning false. Keep the existing fatal handling and successful fan-in flow
unchanged, ensuring the orphaned slot cannot be classified into
graph_prepare_queue.

In `@src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h`:
- Around line 491-513: Update push_ready_routed so the TaskKind::GRAPH branch
stores the result of graph_ready_queue.push in the shared pushed variable and
continues through the existing SCHEDULER_ERROR_READY_QUEUE_OVERFLOW reporting
path instead of returning immediately. Preserve graph queue routing while
ensuring failed graph pushes latch the overflow error.

In `@src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_cold_path.cpp`:
- Around line 1141-1146: Update the GRAPH handling in classify_partition to
avoid retrying graph_prepare_queue.push_tagged when the queue is full. On push
failure, atomically set sched_->sm_header->sched_error_code to
SCHEDULER_ERROR_READY_QUEUE_OVERFLOW using compare_exchange_strong and return,
removing the indefinite SPIN_WAIT_HINT loop.

In `@src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_dispatch.cpp`:
- Around line 946-948: The async dispatch branch currently infers progress only
from stream-task completions, missing internal graph-node completions. Update
AsyncPollResult and poll_and_complete to expose the raw total completion count,
then change the resolved_any update in the async branch to become true whenever
any task completion occurred, while preserving resolved_this_pass’s stream-task
count semantics.
- Around line 1296-1315: Three fatal scheduler paths latch errors without
releasing workers through emergency_shutdown. In
src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_dispatch.cpp#L1296-L1315,
`#L1322-L1334`, and `#L1346-L1358`, extract or reuse a shared fatal-error helper
that performs the existing error latch sequence and invokes
emergency_shutdown(runtime) only once via completed_.exchange(true,
std::memory_order_acq_rel); apply it to the invalid graph-slot, invalid
prepare-slot, and GraphMaterializeResult::INVALID paths.

In `@src/common/host_build_graph/graph_execution_impl.inc`:
- Around line 534-537: Add the existing execution.tensor_patch_capacity bounds
check before indexing execution.tensor_patches in the affine-reuse loop,
matching the guard used by the fresh path. Ensure the function returns the same
failure/status result when execution.materialized_tensor_patches is at capacity,
before reading patch or incrementing the index.

In `@src/common/host_build_graph/graph_execution.h`:
- Around line 225-234: Validate declared wire-image sizes against received
bytes: in src/common/host_build_graph/graph_execution.h#L225-L234, update
graph_submission_definition to reject GraphDefinition::total_bytes values
smaller than sizeof(GraphDefinition) or larger than submission.total_bytes -
submission.definition_offset; in
src/a5/runtime/host_build_graph/host/runtime_maker.cpp#L459-L475, require
upload->bytes >= sizeof(GraphSubmission) before casting and require
submission->total_bytes == upload->bytes afterward. Apply the identical changes
to the corresponding files in src/a2a3/runtime/host_build_graph/ to preserve
byte-for-byte parity.
- Around line 390-394: The graph_submission_signal helper must be retry-safe and
allow activation only once. Update its atomic gate logic to return true only
when this call newly completes BOTH, not when the gate was already complete;
alternatively, guard the activate_prepared_graph call in prepare_graph_task with
an external single-use flag.

---

Outside diff comments:
In `@src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h`:
- Around line 536-544: The documentation for reset_for_reuse must mention both
initialization and affine graph replay as call sites. Update the first sentence
of its comment to state that it runs once per slot at init and again during
affine graph replay, while preserving the remaining binding and scheduling
descriptions.

---

Nitpick comments:
In
`@src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp`:
- Around line 411-417: Add a concise comment immediately before the
producer_index filter in the fanin handling to document that pre-recording
implicit producers are safely dropped because graph_classify_tensor must
classify their tensors as boundary tensors, allowing the outer GRAPH task’s
compute_task_fanin path to rediscover the producer. Do not alter the existing
fanin or unsupported-recording logic.

In `@src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h`:
- Around line 489-503: Pin the current sizeof(PTO2TaskSlotState) with a
static_assert immediately after the struct definition so changes to its tail
padding fail compilation and require layout updates. Update the graph_context
field comment to state that it stores an already-device-address pointer and must
not be relocated. Apply both changes to the corresponding a5 and a2a3
host_build_graph copies, preserving byte-for-byte parity.

In `@src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h`:
- Around line 978-983: Update the completion path containing
graph_execution_from_slot to report invalid execution, definition, node-array,
and node-index state instead of returning a normal empty TaskCompletionOutcome.
Propagate an invalid outcome (or the existing equivalent) to its callers so they
latch PTO2_ERROR_INVALID_ARGS and stop the run consistently with
scheduler_dispatch.cpp, while preserving normal completion behavior for valid
state.

In `@src/common/host_build_graph/graph_execution_impl.inc`:
- Around line 108-112: Add a compile-time assertion next to the observed_magic
read in the reuse probe, using GraphExecution and storage_magic to enforce that
storage_magic remains at offset 0 and retains the expected 8-byte width. Keep
the existing memcpy and reusable_execution_header_valid flow unchanged.

In `@src/common/host_build_graph/graph_execution.h`:
- Around line 300-317: Add concise comments beside the paired fields in the
relevant state structure: document that materialized_nodes and
materialized_tensor_patches are incremental cursors while their *_count
counterparts are finalized totals, and clarify whether nodes or node_storage
owns the allocation. Preserve all existing field names and behavior, including
graph_execution_materialize_slice’s cross-call updates.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7fb95e28-43a9-4b3d-a2b4-29e862d1e872

📥 Commits

Reviewing files that changed from the base of the PR and between 53dfa3e and 6f34d82.

📒 Files selected for processing (44)
  • docs/troubleshooting/device-error-codes.md
  • docs/troubleshooting/device-error-codes/README.md
  • docs/troubleshooting/device-error-codes/untested.md
  • src/a2a3/docs/runtimes.md
  • src/a2a3/runtime/host_build_graph/common/pto_runtime_status.h
  • src/a2a3/runtime/host_build_graph/docs/GRAPH_EXECUTION.md
  • src/a2a3/runtime/host_build_graph/runtime/graph_cache.h
  • src/a2a3/runtime/host_build_graph/runtime/graph_execution.h
  • src/a2a3/runtime/host_build_graph/runtime/graph_host_state.h
  • src/a2a3/runtime/host_build_graph/runtime/scheduler/graph_execution.cpp
  • src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
  • src/a5/docs/runtimes.md
  • src/a5/runtime/host_build_graph/common/pto_runtime_status.h
  • src/a5/runtime/host_build_graph/docs/GRAPH_EXECUTION.md
  • src/a5/runtime/host_build_graph/host/runtime_maker.cpp
  • src/a5/runtime/host_build_graph/orchestration/pto_orchestration_api.h
  • src/a5/runtime/host_build_graph/runtime/graph_cache.h
  • src/a5/runtime/host_build_graph/runtime/graph_execution.h
  • src/a5/runtime/host_build_graph/runtime/graph_host_state.h
  • src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp
  • src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_runtime2.cpp
  • src/a5/runtime/host_build_graph/runtime/pto_orchestrator.h
  • src/a5/runtime/host_build_graph/runtime/pto_runtime2.h
  • src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h
  • src/a5/runtime/host_build_graph/runtime/pto_submit_types.h
  • src/a5/runtime/host_build_graph/runtime/scheduler/graph_execution.cpp
  • src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
  • src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_cold_path.cpp
  • src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_dispatch.cpp
  • src/a5/runtime/host_build_graph/runtime/shared/pto_runtime2_init.cpp
  • src/common/host_build_graph/docs/GRAPH_EXECUTION.md
  • src/common/host_build_graph/graph_cache.h
  • src/common/host_build_graph/graph_execution.h
  • src/common/host_build_graph/graph_execution_impl.inc
  • src/common/host_build_graph/graph_host_state.h
  • src/common/runtime_status/error_names.h
  • tests/st/a5/host_build_graph/graph_execution/kernels/orchestration/graph_execution_aic_aiv_orch.cpp
  • tests/st/a5/host_build_graph/graph_execution/kernels/orchestration/graph_execution_mix_spmd_orch.cpp
  • tests/st/a5/host_build_graph/graph_execution/kernels/orchestration/graph_execution_orch.cpp
  • tests/st/a5/host_build_graph/graph_execution/test_graph_execution.py
  • tests/st/a5/host_build_graph/graph_execution/test_graph_execution_aic_aiv.py
  • tests/st/a5/host_build_graph/graph_execution/test_graph_execution_mix_spmd.py
  • tests/ut/cpp/CMakeLists.txt
  • tests/ut/cpp/common/test_hbg_graph_cache.cpp

Comment thread docs/troubleshooting/device-error-codes.md Outdated
Comment thread docs/troubleshooting/device-error-codes.md Outdated
Comment thread src/a2a3/runtime/host_build_graph/common/pto_runtime_status.h Outdated
Comment thread src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h Outdated
Comment thread src/a5/runtime/host_build_graph/host/runtime_maker.cpp
Comment thread src/common/host_build_graph/graph_execution_impl.inc Outdated
Comment thread src/common/host_build_graph/graph_execution.h Outdated
Comment thread src/common/host_build_graph/graph_execution.h Outdated
@zmnobug

zmnobug commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the review follow-ups in c3e6b60:

  • Updated the reset_for_reuse comment to cover initialization and affine replay.
  • Clarified the materialization cursors, finalized counts, and node-storage ownership.
  • Documented that graph_context holds an already-device address. The existing PTO2TaskSlotState size static_assert already pins the shared-memory layout, so no duplicate assertion was added.
  • Added compile-time checks for the storage_magic offset and width.
  • Documented why pre-recording implicit producers are represented through Graph boundaries.
  • Propagated invalid Graph-node completion state as PTO2_ERROR_INVALID_ARGS through the scheduler shutdown path.

I also replied to all 13 inline threads with the corresponding fix or verification result. Validation passed: repository pre-commit hooks, the full non-hardware C++ unit suite (91/91 effective), A2/A3 HBG simulation (27 passed, 4 skipped), and A5 HBG simulation (18 passed). The sandbox socket restriction and Conda GCC ABI issues both passed on their isolated or environment-corrected reruns.

@ChaoZheng109 ChaoZheng109 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

审了一遍,先说结论:移植保真度很高。我用 merge-base 上的 a2a3 做基线逐文件比对,pto_scheduler.hscheduler_cold_path.cpporchestrator_core/pto_runtime2.cpp 移植后与 a2a3 逐字节相同(移植前的差异 100% 就是缺失的 graph 代码);pto_orchestrator.cpp 从 766 行差异降到 49 行,且这 49 行全部是移植前就存在的 a5 本地差异。PTO2TaskSlotState 新增两个字段后 static_assert(sizeof == 64) 仍成立,graph 队列在 pto_runtime2_init.cpp 的预留/wire/destroy 三处也都接上了。

特别想指出 scheduler_dispatch.cpprun_resolution_threadresolved_any 处理——a5 的 P 线程自己维护 completed_/new_total 完成判定(a2a3 没有这段),图内节点 stream_tasks_completed == 0 会让 resolved_this_pass 保持 0。把"有进展"和"完成计数增加"拆开是必要的:直接照抄 a2a3 的话,图展开期间 P 线程会误判为无进展并触发 scheduler stall 超时。这是真正的移植工作,不是复制。

具体问题都标在对应行上了,汇总如下:

🔴 Must fix

  1. 基线过时,rebase 到当前 main 后会编译失败 —— 3 处行内评论:graph_execution.h:50pto_orchestrator.cpp:333scheduler/graph_execution.cpp:478

🟡 Should fix

  1. tests/ut/cpp/a5/test_graph_cache.cpp 与 a2a3 版本逐字节相同,应改用仓库已有的跨 arch 共享模式 —— tests/ut/cpp/CMakeLists.txt:789
  2. AIC/AIV 场景的图内 fan-in 覆盖需要补回来 —— graph_execution_aic_aiv_orch.cpp:26
  3. qwen3_14b_3layer 场景需要补上(4 个场景现在只有 3 个) —— docs/GRAPH_EXECUTION.md:349
  4. 移植时漏了 GraphFunction 上方的契约注释 —— pto_orchestration_api.h:375

以上 5 条处理完再 approve。

另外 rebase 之后还需要再镜像一次 #1712(Graph 边界动态 scalar),a5 现在复制的是 step-1 的 scalar_count() == 0 断言——这已经是第二次需要手工同步了(#1729#1712),建议把这个成本写进 #1737 作为尽快抽取共用实现的依据。

Comment thread src/a5/runtime/host_build_graph/runtime/graph_execution.h Outdated
Comment thread src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.cpp Outdated
Comment thread src/a5/runtime/host_build_graph/runtime/scheduler/graph_execution.cpp Outdated
Comment thread tests/ut/cpp/CMakeLists.txt
Comment thread src/a5/runtime/host_build_graph/docs/GRAPH_EXECUTION.md Outdated
@zmnobug
zmnobug force-pushed the feat/issue-1715-port-graph-execution-a5 branch 2 times, most recently from dff77e1 to e32df3a Compare August 10, 2026 06:03
@zmnobug
zmnobug force-pushed the feat/issue-1715-port-graph-execution-a5 branch 2 times, most recently from 4ab2e7d to 81d3b91 Compare August 10, 2026 08:00
- Port A2/A3 Graph recording, cache, materialization, and replay into A5 without changing the reference implementation
- Add A5 host upload, retained execution buffers, and runtime lifecycle hooks
- Cover AIV, mixed AIC/AIV fan-in, MIX/SPMD, and the A5 Graph cache unit test
- Keep current address-space and TensorArg ABI compatibility
- Track cross-architecture hardening in hw-native-sys#1736 and sharing in hw-native-sys#1737
@ChaoZheng109
ChaoZheng109 merged commit 4739cbf into hw-native-sys:main Aug 10, 2026
30 of 35 checks passed
ChaoZheng109 added a commit that referenced this pull request Aug 11, 2026
…h_ready safe-fail (#1773)

Mirror of #1762 for a5. a5 gained Graph execution in #1733, which also copied
a2a3's pre-#1762 push_ready_routed — including the graph_ready push that
ignored its return value, so a full graph_ready_queue would silently drop a
task and stall. Apply the same two changes #1762 landed for a2a3:

  - PTO2_READY_QUEUE_SIZE 65536 -> 8192. The Vyukov ring bounds peak concurrent
    occupancy (enqueue_pos - dequeue_pos), not total task count, so capacity
    need only exceed the worst-case ready burst with margin.
  - push_ready_routed: route the GRAPH task through the same checked push as
    ready/sync/dummy so a full graph_ready_queue latches
    PTO2_ERROR_READY_QUEUE_OVERFLOW (named emergency_shutdown) instead of a
    silent drop.

a5 push_ready_routed was byte-identical to a2a3 pre-#1762, so this is a 1:1
mirror; both regions are now identical across the two arches. The
PTO2_ERROR_READY_QUEUE_OVERFLOW 104 code was already added to a5's error enum
by #1733, so no enum change is needed here.
ChaoZheng109 added a commit that referenced this pull request Aug 11, 2026
Ports a2a3 host_build_graph PR #1732 to A5. The A5 runtime was ported
in #1733 from an a2a3 snapshot predating #1732; the parity follow-ups
#1736/#1737 it promised were never opened, so A5 has been missing
dynamic Graph boundary scalar support.

Mirrors #1732 line-for-line (the two trees are structurally identical
on this surface):

- Arg tracks scalar provenance (source pointer + invalidation flag)
  across add_scalars/add_scalars_i32/add_scalar_one/copy_scalars_from;
  a mutable scalar() access invalidates a forwarded boundary source so
  it is re-read at replay.
- New wire/POD types GraphScalarSource, GraphScalarSourceRef,
  GraphScalarPatch; GraphDefinition gains boundary_scalar_count and
  off_scalar_sources; GraphSubmission replaces its reserved pad with
  scalars_offset + scalar_count.
- graph_execution_storage_layout/_bytes gain a scalar_patch_capacity
  argument; all call sites updated together.
- Recording classifies each scalar as static or boundary; the Definition
  stores boundary provenance, and first materialization plus affine
  replay refresh only the dynamic scalar slots.
- rt_graph_args_cacheable and rt_submit_graph_impl drop the
  scalar_count()==0 rejection that previously forbade boundary scalars.

Verified: full no-hardware C++ unit suite (92/92, including new
test_a5_graph_cache boundary-scalar cases) and the A5 graph_execution
a5sim scenes (3/3).
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.

[Feature] hbg: Port Graph Execution to a5

3 participants