Skip to content

Add: support dynamic Graph boundary scalars on A5 - #1777

Merged
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
ChaoZheng109:port-1732-a5-dynamic-scalars
Aug 11, 2026
Merged

Add: support dynamic Graph boundary scalars on A5#1777
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
ChaoZheng109:port-1732-a5-dynamic-scalars

Conversation

@ChaoZheng109

Copy link
Copy Markdown
Collaborator

Ports a2a3 host_build_graph PR #1732 (dynamic Graph boundary scalars) to A5.

Why

A5 Graph Execution was ported in #1733 from an a2a3 snapshot taken before #1732 landed. #1733 deferred cross-arch parity to follow-ups #1736/#1737, which were never opened — so the A5 HBG runtime has been sitting at the pre-#1732 baseline, missing dynamic Graph boundary scalar support (boundary CoreTaskArgs with scalars were rejected with "… not supported in step 1").

This closes that gap. The a2a3 and A5 HBG trees are structurally identical on the touched surface (shared base TaskArgsTpl in src/common/task_interface/task_args.h), so this is a line-for-line port of already-reviewed a2a3 code.

What (mirrors #1732)

  • pto_types.hArg tracks scalar provenance (source pointer + invalidation flag) across add_scalars / add_scalars_i32 / add_scalar_one / copy_scalars_from; a mutable scalar(i) access invalidates a forwarded boundary source so it is re-read at replay.
  • graph_execution.h — 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.
  • scheduler/graph_execution.cpp — 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 (leaving static slots untouched).
  • graph_cache.h / pto_orchestration_api.h — drop the scalar_count()==0 rejection that previously forbade boundary scalars.
  • Storage-signature change is atomic across all call sites (runtime_maker.cpp, scheduler, unit test).

This is PR 1 of 2; PR 2 ports #1731 (record Graph off the ring) on top of this branch.

Testing

  • Editable runtime build (a5 onboard + a5sim)
  • Full no-hardware C++ unit suite: 92/92 (incl. new test_a5_graph_cache boundary-scalar cases: AcceptsBoundaryScalars, ConfigValuesSelectDifferentDefinitions, GraphScalarProvenance.*)
  • A5 graph_execution a5sim scenes: 3/3
  • Pre-commit (clang-format, clang-tidy, cpplint, markdownlint, pyright, ruff)
  • A5 onboard hardware CI

Refs #1732.

🤖 Generated with Claude Code

Ports a2a3 host_build_graph PR hw-native-sys#1732 to A5. The A5 runtime was ported
in hw-native-sys#1733 from an a2a3 snapshot predating hw-native-sys#1732; the parity follow-ups
hw-native-sys#1736/hw-native-sys#1737 it promised were never opened, so A5 has been missing
dynamic Graph boundary scalar support.

Mirrors hw-native-sys#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).

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 16dfed38-7746-4cdf-9b2e-018550ef05c8

📥 Commits

Reviewing files that changed from the base of the PR and between ecbc2ee and 0f95ae6.

📒 Files selected for processing (11)
  • 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/orchestrator_core/pto_orchestrator.cpp
  • src/a5/runtime/host_build_graph/runtime/pto_types.h
  • src/a5/runtime/host_build_graph/runtime/scheduler/graph_execution.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/ut/cpp/a5/test_graph_cache.cpp

📝 Walkthrough

Walkthrough

The graph runtime now supports dynamic boundary scalar arguments. It tracks scalar provenance, serializes scalar source metadata, allocates scalar patch storage, refreshes boundary values during replay, and validates cacheability, storage, and scalar-count constraints.

Changes

Dynamic scalar replay

Layer / File(s) Summary
Scalar provenance and wire contracts
src/a5/runtime/host_build_graph/runtime/pto_types.h, src/a5/runtime/host_build_graph/runtime/graph_execution.h
Scalar sources now track provenance and invalidation state. Graph definitions, submissions, and execution storage now include scalar metadata and scalar patch regions.
Recording and submission serialization
src/a5/runtime/host_build_graph/runtime/orchestrator_core/pto_orchestrator.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/host/runtime_maker.cpp
Recording classifies static and boundary scalars. Definitions serialize source references. Submissions carry runtime scalar values. Scalar-containing arguments can enter the cache when other checks pass.
Storage and replay materialization
src/a5/runtime/host_build_graph/runtime/scheduler/graph_execution.cpp
Execution storage allocates scalar patch capacity. Materialization resolves scalar sources and affine replay reapplies boundary scalar patches.
Examples and replay validation
src/a5/runtime/host_build_graph/docs/GRAPH_EXECUTION.md, tests/st/a5/host_build_graph/graph_execution/..., tests/ut/cpp/a5/test_graph_cache.cpp
Documentation and tests cover dynamic scalar forwarding, cache keys, provenance, storage layout, static-value preservation, and replay updates.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant GraphRecorder
  participant GraphDefinition
  participant GraphExecution
  participant BoundaryScalars
  Caller->>GraphRecorder: submit graph with scalar arguments
  GraphRecorder->>GraphDefinition: record scalar source references
  GraphDefinition->>GraphExecution: materialize graph definition
  GraphExecution->>BoundaryScalars: read runtime boundary scalar values
  BoundaryScalars->>GraphExecution: provide scalar values
  GraphExecution->>GraphExecution: apply scalar patches during replay
Loading

Possibly related PRs

Poem

A rabbit patches scalars with care,
Refreshing values in replayed air.
Static numbers stay in their place,
Boundary inputs change the race.
The graph hops on, aligned and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.23% 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
Title check ✅ Passed The title clearly and concisely describes the main change: dynamic Graph boundary scalar support on A5.
Description check ✅ Passed The description directly explains the A5 port, implementation scope, testing, and remaining hardware CI work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@ChaoZheng109
ChaoZheng109 merged commit 7b3a975 into hw-native-sys:main Aug 11, 2026
18 checks passed
ChaoZheng109 added a commit to ChaoZheng109/simpler that referenced this pull request Aug 11, 2026
…RAPH task

Ports a2a3 host_build_graph PR hw-native-sys#1731 to A5.

Mirrors hw-native-sys#1731 line-for-line. With hw-native-sys#1777 in place, the scalar-source
machinery hw-native-sys#1731's recording path depends on now exists on A5, so the
port is direct:

- PTO2TaskAllocator gains reserve_heap_scratch / restore_heap_top.
- The recording pass routes submit_task / submit_dummy_task /
  alloc_tensors to graph_record_submit_node, which records each node's
  layout off the ring — output buffers come from heap scratch (released
  in graph_end) instead of a task-window slot. No ring slot, tensormap,
  fanin-pool entry, or upload is produced for an internal node.
- A scope inside a Graph body is a no-op during recording.
- graph_end rolls the heap back to the recording watermark, compacts and
  caches the Definition, and emits the single outer GRAPH task. It now
  returns bool; when the outer task cannot be placed, the body re-runs on
  the ordinary path so its work is still submitted.
- The graph_end ops-table entry changes void -> bool in both mirrored
  ops structs.

The first invocation now occupies one ring slot and one heap block
instead of one per internal node.

Verified: full no-hardware C++ unit suite (92/92) and the A5
graph_execution a5sim scenes (3/3).
ChaoZheng109 added a commit that referenced this pull request Aug 11, 2026
…RAPH task (#1780)

Ports a2a3 host_build_graph PR #1731 to A5.

Mirrors #1731 line-for-line. With #1777 in place, the scalar-source
machinery #1731's recording path depends on now exists on A5, so the
port is direct:

- PTO2TaskAllocator gains reserve_heap_scratch / restore_heap_top.
- The recording pass routes submit_task / submit_dummy_task /
  alloc_tensors to graph_record_submit_node, which records each node's
  layout off the ring — output buffers come from heap scratch (released
  in graph_end) instead of a task-window slot. No ring slot, tensormap,
  fanin-pool entry, or upload is produced for an internal node.
- A scope inside a Graph body is a no-op during recording.
- graph_end rolls the heap back to the recording watermark, compacts and
  caches the Definition, and emits the single outer GRAPH task. It now
  returns bool; when the outer task cannot be placed, the body re-runs on
  the ordinary path so its work is still submitted.
- The graph_end ops-table entry changes void -> bool in both mirrored
  ops structs.

The first invocation now occupies one ring slot and one heap block
instead of one per internal node.

Verified: full no-hardware C++ unit suite (92/92) 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.

1 participant