Skip to content

feat(a2a3/dispatch): sync_start strict Tier-0 + shared staging order#1319

Merged
ChaoWao merged 2 commits into
hw-native-sys:mainfrom
ChaoWao:feat/dispatch-sync-start-tier
Jul 10, 2026
Merged

feat(a2a3/dispatch): sync_start strict Tier-0 + shared staging order#1319
ChaoWao merged 2 commits into
hw-native-sys:mainfrom
ChaoWao:feat/dispatch-sync-start-tier

Conversation

@ChaoWao

@ChaoWao ChaoWao commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Aligns the a2a3 tensormap_and_ringbuffer scheduler dispatch with a single
occupancy model: two task sources (normal ready ▸ speculative early), and
within each source sync_start > MIX > C/V, idle > pending.
Two commits:

  1. refactor — one shared staging-order skeleton. dispatch_ready_tasks and
    try_early_dispatch each carried a hand-mirrored copy of the same order (MIX
    strict priority, IDLE before PENDING, cross-thread idle gating). Extract it
    into one run_staging_order helper parameterized by the per-shape stage
    callback; the two sources now differ only in that callback (normal = pickup /
    is_ready, early = gated). Behavior-identical.

  2. feat — ready sync_start as strict Tier-0 in normal dispatch. Normal
    sync_start cohorts previously rode ready_queues[shape] mixed with regular
    tasks, so an AIC/AIV sync waited behind regular MIX. Park ready sync_start in
    dedicated per-shape ready_sync_queues[] and drain them as a Tier-0 pass
    before regular ready work. The pass reuses dispatch_shape unchanged
    (now parameterized by the queue array): same fits-local-inline vs
    stop-the-world drain decision, per-core MIX placement, per-task head-start
    spacing. The regular tier passes ready_queues exactly as before, so regular
    dispatch is byte-identical; the early-dispatch gate now also drains the sync
    lanes so early never preempts a queued normal sync.

Scope / notes

  • a2a3 tensormap_and_ringbuffer only. Regular dispatch path unchanged;
    risk is isolated to the new sync Tier-0 pass and the shared-order extraction.
  • Independent of the sync_start early-dispatch work (Add: early-dispatch for require_sync_start SPMD cohorts (a2a3 tmr) #1304) — this only adds the
    normal-source sync tier + the order unification; the early-source sync
    tier lands separately.

Testing

  • a2a3sim: 13 scene tests (sync_start family, MIX, starvation, paged
    attention, alternating, fanin, oob) — pass.
  • a2a3 onboard (device-locked): 8 scene tests + spmd_sync_start_stress
    x30, 0 failures, no 507018
    .

🤖 Generated with Claude Code

…mal and early

dispatch_ready_tasks and try_early_dispatch each carried a hand-mirrored copy of
the same occupancy order (MIX strict priority, IDLE before PENDING, cross-thread
idle gating). Extract it into one run_staging_order helper parameterized by the
per-shape stage callback: normal passes dispatch_shape (pickup, is_ready) and
signals stop via entered_drain; early passes early_dispatch_shape (gated) and
never stops. Behavior-identical — same order, gates, PMU handling, and progress
accounting; the two sources now differ only in the stage callback (is_ready).

Verified golden-exact: a2a3sim 13 scene tests, a2a3 onboard 10 scene tests
(sync_start family, MIX, starvation, paged-attention, alternating) all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 10, 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

Run ID: 347f6835-d146-4753-8023-eb60202212fc

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 scheduler adds per-resource-shape sync_start ready queues, routes matching tasks into them, manages their arena storage, and drains them as Tier 0 work before regular ready queues. Dispatch and early-dispatch staging now share queue-aware ordering logic.

Changes

Sync-start scheduler flow

Layer / File(s) Summary
Sync-start queue storage
src/a2a3/.../scheduler/pto_scheduler.h, src/a2a3/.../shared/pto_runtime2_init.cpp
Adds per-shape sync-start queue state, arena offsets, initialization, reset, pointer wiring, and destruction.
Ready-task routing
src/a2a3/.../scheduler/pto_scheduler.h, src/a2a3/.../scheduler/scheduler_context.h
Routes requires_sync_start() tasks to dedicated queues and makes batch popping accept explicit queue arrays.
Queue-aware dispatch
src/a2a3/.../scheduler/scheduler_dispatch.cpp
Passes selected queues through shape dispatch and all task requeue paths.
Tiered staging and early dispatch
src/a2a3/.../scheduler/scheduler_context.h, src/a2a3/.../scheduler/scheduler_dispatch.cpp
Centralizes staging order, drains sync-start work before regular work, and blocks early dispatch when either queue tier contains tasks.

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

Possibly related PRs

Poem

I’m a bunny with queues in a row,
Sync-start hops first, then regulars go.
MIX finds its place, staging runs bright,
Early dispatch checks both lanes right.
Thump-thump—the scheduler’s flow takes flight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly highlights the main change: strict Tier-0 sync_start handling plus shared staging order.
Description check ✅ Passed The description matches the changeset and accurately describes the sync_start Tier-0 flow and shared staging-order refactor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

@gemini-code-assist

Copy link
Copy Markdown

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@ChaoWao ChaoWao force-pushed the feat/dispatch-sync-start-tier branch 2 times, most recently from 2c61182 to 3b5cb55 Compare July 10, 2026 04:51
…atch

Normal-source sync_start cohorts previously rode ready_queues[shape] mixed with
regular tasks, so an AIC/AIV sync waited behind regular MIX work — the occupancy
order was MIX > C/V with no sync tier. Give sync_start strict priority within the
normal source (sync_start > MIX > C/V, idle > pending) by parking ready
sync_start cohorts in dedicated per-shape ready_sync_queues[] and draining them
as a Tier-0 pass before regular ready work.

The Tier-0 pass reuses dispatch_shape unchanged (now parameterized by the queue
array): same fits-local inline vs stop-the-world drain decision, per-core MIX
placement, and per-task head-start spacing. The regular tier passes ready_queues
exactly as before, so regular dispatch is byte-identical. early dispatch already
sits strictly after all normal work; its gate now also drains the sync lanes so
early never preempts a queued normal sync.

Verified: a2a3sim 14 scene tests; a2a3 onboard 9 scene tests + 30x
spmd_sync_start_stress (0 failures, no 507018).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChaoWao ChaoWao merged commit 53114ef into hw-native-sys:main Jul 10, 2026
15 checks passed
@ChaoWao ChaoWao deleted the feat/dispatch-sync-start-tier branch July 10, 2026 14:25
ChaoWao added a commit to ChaoWao/simpler-fork that referenced this pull request Jul 11, 2026
…gbuffer

hbg's scheduler was a copy of tmr@fb28fd71 and had fallen a full generation
behind. This absorbs tmr's post-fork scheduler evolution while preserving hbg's
host-orchestration invariants (single ring, no execution-time reclaim, flat
Runtime, host-side orchestrator).

Absorbed from tmr:
- Remove PTO2LocalReadyBuffer local-first dispatch and its local_bufs threading
  (hw-native-sys#1245); pop/dispatch now take PTO2ReadyQueue* directly.
- Ready-claim completion protocol: ready_state / mark_completed /
  mark_any_subtask_deferred (replaces the any_subtask_deferred bool).
- Rename speculative -> early_dispatch and remove the auto-chain
  (spec_chain_active/depth, PTO2_SPEC_CHAIN_MAX); move allow_early_resolve from
  payload onto slot_state.
- Per-shape early_dispatch_queues[] (was a single queue) + ready_sync_queues[]
  Tier-0 sync_start staging (hw-native-sys#1319); run_staging_order template;
  try_early_dispatch / early_dispatch_shape; has_any_free_slot predicates.
- MIX subtasks placed per-core instead of uniform cluster placement (hw-native-sys#1308).
- Remove the on-device wiring subsystem (PTO2SpscQueue / WiringState /
  drain_wiring_queue / wire_task, hw-native-sys#1263): the host orchestrator now wires fanout
  adjacency inline during submit and seeds readiness via the scheduler's
  push_ready_routed / route_ready_once, with no device-side wiring queue.
- Single-round-trip / parallel AICore handshake (hw-native-sys#1279/hw-native-sys#1310): handshake_all_cores
  -> pre_handshake_init + per-thread handshake_partition + post_handshake_init,
  with the matching aicpu_executor boot restructure and AICore-worker protocol.
- Drop the per-run per-core memset in scheduler init/deinit (hw-native-sys#1212); gate dep_gen
  init under SIMPLER_DFX; compile out pmu_active when SIMPLER_DFX is off; remove
  the redundant second completion poll; remove the dead device-orch core
  transition (handle_core_transition / reassign_cores_for_all_threads /
  orch_to_sched_).

Remove vestigial device-orch synchronization: with host orchestration the
orchestrator runs to completion on the host before the device boots, so the
device-side orchestrator_done_ flag is always set before the scheduler threads
start (they gate on runtime_init_ready_, whose release/acquire already publishes
total_tasks_). Removed orchestrator_done_, the always-true completion guard, and
the never-called wait_for_orchestration_done_before_dispatch / orchestration_done()
carried over from tmr's concurrent device-orch model.

Preserved host-orch divergences (not overwritten by tmr): PTO2_MAX_RING_DEPTH==1
with rings[]/ring_id removed; no advance_ring_pointers / reset_for_reuse /
check_and_handle_consumed (completion via completed_tasks_, consumer wait keys on
fanout_refcount); flat runtime->workers; hbg's swimlane behavior (no on_aicore_ack
hook — the just-filled buffer drains via the completion-before-dispatch invariant
and the next-rotation / run-end backstop flushes).

Skipped as not applicable to hbg: stall-classification publishing (shared-memory
lacks the sched_stall_* fields; last_task_alive semantics differ); per-device
scheduler timeout (aicpu_device_config.h / get_scheduler_timeout_ms absent);
runtime->dev.* Runtime nesting.

get_reg_ptr weak host fallback: route_ready_once transitively ODR-uses the
early-dispatch doorbell inline (ring_one_doorbell -> get_reg_ptr) in the host
lib, but no core is gated during host graph-build so it never fires; a weak
hidden fallback satisfies the loader (same pattern as get_sys_cnt_aicpu).

Verified: all 8 runtime targets build -Werror; a2a3sim host_build_graph scene
suite 10/10; a2a3 onboard host_build_graph suite 10 passed / 1 skipped
(paged_attention exercises the new handshake, route_ready_once wiring, and
ready-claim path). tensormap_and_ringbuffer and the a5 runtimes are untouched.
ChaoWao added a commit to ChaoWao/simpler-fork that referenced this pull request Jul 11, 2026
…gbuffer

hbg's scheduler was a copy of tmr@fb28fd71 and had fallen a full generation
behind. This absorbs tmr's post-fork scheduler evolution while preserving hbg's
host-orchestration invariants (single ring, no execution-time reclaim, flat
Runtime, host-side orchestrator).

Absorbed from tmr:
- Remove PTO2LocalReadyBuffer local-first dispatch and its local_bufs threading
  (hw-native-sys#1245); pop/dispatch now take PTO2ReadyQueue* directly.
- Ready-claim completion protocol: ready_state / mark_completed /
  mark_any_subtask_deferred (replaces the any_subtask_deferred bool).
- Rename speculative -> early_dispatch and remove the auto-chain
  (spec_chain_active/depth, PTO2_SPEC_CHAIN_MAX); move allow_early_resolve from
  payload onto slot_state.
- Per-shape early_dispatch_queues[] (was a single queue) + ready_sync_queues[]
  Tier-0 sync_start staging (hw-native-sys#1319); run_staging_order template;
  try_early_dispatch / early_dispatch_shape; has_any_free_slot predicates.
- MIX subtasks placed per-core instead of uniform cluster placement (hw-native-sys#1308).
- Remove the on-device wiring subsystem (PTO2SpscQueue / WiringState /
  drain_wiring_queue / wire_task, hw-native-sys#1263): the host orchestrator now wires fanout
  adjacency inline during submit and seeds readiness via the scheduler's
  push_ready_routed / route_ready_once, with no device-side wiring queue.
- Single-round-trip / parallel AICore handshake (hw-native-sys#1279/hw-native-sys#1310): handshake_all_cores
  -> pre_handshake_init + per-thread handshake_partition + post_handshake_init,
  with the matching aicpu_executor boot restructure and AICore-worker protocol.
  Drop the now-dead two-round-trip Handshake fields aicpu_regs_ready /
  aicore_regs_ready (aligning the struct to tmr's).
- Drop the per-run per-core memset in scheduler init/deinit (hw-native-sys#1212); gate dep_gen
  init under SIMPLER_DFX; compile out pmu_active when SIMPLER_DFX is off; remove
  the redundant second completion poll; remove the dead device-orch core
  transition (handle_core_transition / reassign_cores_for_all_threads /
  orch_to_sched_).

Remove vestigial device-orch synchronization: with host orchestration the
orchestrator runs to completion on the host before the device boots, so the
device-side orchestrator_done_ flag is always set before the scheduler threads
start (they gate on runtime_init_ready_, whose release/acquire already publishes
total_tasks_). Removed orchestrator_done_, the always-true completion guard, and
the never-called wait_for_orchestration_done_before_dispatch / orchestration_done()
carried over from tmr's concurrent device-orch model.

Preserved host-orch divergences (not overwritten by tmr): PTO2_MAX_RING_DEPTH==1
with rings[]/ring_id removed; no advance_ring_pointers / reset_for_reuse /
check_and_handle_consumed (completion via completed_tasks_, consumer wait keys on
fanout_refcount); flat runtime->workers; hbg's swimlane behavior (no on_aicore_ack
hook — the just-filled buffer drains via the completion-before-dispatch invariant
and the next-rotation / run-end backstop flushes).

Skipped as not applicable to hbg: stall-classification publishing (shared-memory
lacks the sched_stall_* fields; last_task_alive semantics differ); per-device
scheduler timeout (aicpu_device_config.h / get_scheduler_timeout_ms absent);
runtime->dev.* Runtime nesting.

get_reg_ptr weak host fallback: route_ready_once transitively ODR-uses the
early-dispatch doorbell inline (ring_one_doorbell -> get_reg_ptr) in the host
lib, but no core is gated during host graph-build so it never fires; a weak
hidden fallback satisfies the loader (same pattern as get_sys_cnt_aicpu).

Verified: all 8 runtime targets build -Werror; a2a3sim host_build_graph scene
suite 10/10; a2a3 onboard host_build_graph suite 10 passed / 1 skipped
(paged_attention exercises the new handshake, route_ready_once wiring, and
ready-claim path). tensormap_and_ringbuffer and the a5 runtimes are untouched.
ChaoWao added a commit that referenced this pull request Jul 11, 2026
…gbuffer (#1327)

hbg's scheduler was a copy of tmr@fb28fd71 and had fallen a full generation
behind. This absorbs tmr's post-fork scheduler evolution while preserving hbg's
host-orchestration invariants (single ring, no execution-time reclaim, flat
Runtime, host-side orchestrator).

Absorbed from tmr:
- Remove PTO2LocalReadyBuffer local-first dispatch and its local_bufs threading
  (#1245); pop/dispatch now take PTO2ReadyQueue* directly.
- Ready-claim completion protocol: ready_state / mark_completed /
  mark_any_subtask_deferred (replaces the any_subtask_deferred bool).
- Rename speculative -> early_dispatch and remove the auto-chain
  (spec_chain_active/depth, PTO2_SPEC_CHAIN_MAX); move allow_early_resolve from
  payload onto slot_state.
- Per-shape early_dispatch_queues[] (was a single queue) + ready_sync_queues[]
  Tier-0 sync_start staging (#1319); run_staging_order template;
  try_early_dispatch / early_dispatch_shape; has_any_free_slot predicates.
- MIX subtasks placed per-core instead of uniform cluster placement (#1308).
- Remove the on-device wiring subsystem (PTO2SpscQueue / WiringState /
  drain_wiring_queue / wire_task, #1263): the host orchestrator now wires fanout
  adjacency inline during submit and seeds readiness via the scheduler's
  push_ready_routed / route_ready_once, with no device-side wiring queue.
- Single-round-trip / parallel AICore handshake (#1279/#1310): handshake_all_cores
  -> pre_handshake_init + per-thread handshake_partition + post_handshake_init,
  with the matching aicpu_executor boot restructure and AICore-worker protocol.
  Drop the now-dead two-round-trip Handshake fields aicpu_regs_ready /
  aicore_regs_ready (aligning the struct to tmr's).
- Drop the per-run per-core memset in scheduler init/deinit (#1212); gate dep_gen
  init under SIMPLER_DFX; compile out pmu_active when SIMPLER_DFX is off; remove
  the redundant second completion poll; remove the dead device-orch core
  transition (handle_core_transition / reassign_cores_for_all_threads /
  orch_to_sched_).

Remove vestigial device-orch synchronization: with host orchestration the
orchestrator runs to completion on the host before the device boots, so the
device-side orchestrator_done_ flag is always set before the scheduler threads
start (they gate on runtime_init_ready_, whose release/acquire already publishes
total_tasks_). Removed orchestrator_done_, the always-true completion guard, and
the never-called wait_for_orchestration_done_before_dispatch / orchestration_done()
carried over from tmr's concurrent device-orch model.

Preserved host-orch divergences (not overwritten by tmr): PTO2_MAX_RING_DEPTH==1
with rings[]/ring_id removed; no advance_ring_pointers / reset_for_reuse /
check_and_handle_consumed (completion via completed_tasks_, consumer wait keys on
fanout_refcount); flat runtime->workers; hbg's swimlane behavior (no on_aicore_ack
hook — the just-filled buffer drains via the completion-before-dispatch invariant
and the next-rotation / run-end backstop flushes).

Skipped as not applicable to hbg: stall-classification publishing (shared-memory
lacks the sched_stall_* fields; last_task_alive semantics differ); per-device
scheduler timeout (aicpu_device_config.h / get_scheduler_timeout_ms absent);
runtime->dev.* Runtime nesting.

get_reg_ptr weak host fallback: route_ready_once transitively ODR-uses the
early-dispatch doorbell inline (ring_one_doorbell -> get_reg_ptr) in the host
lib, but no core is gated during host graph-build so it never fires; a weak
hidden fallback satisfies the loader (same pattern as get_sys_cnt_aicpu).

Verified: all 8 runtime targets build -Werror; a2a3sim host_build_graph scene
suite 10/10; a2a3 onboard host_build_graph suite 10 passed / 1 skipped
(paged_attention exercises the new handshake, route_ready_once wiring, and
ready-claim path). tensormap_and_ringbuffer and the a5 runtimes are untouched.
ChaoWao added a commit that referenced this pull request Jul 11, 2026
…gbuffer (#1335)

Follows PR #1327 (which synced hbg's scheduler to tmr's #1319 state). tmr then
landed five more early-dispatch changes on the same subsystem; this ports them
into host_build_graph's copies, preserving hbg's host-orchestration invariants
(single ring, no execution-time reclaim, flat Runtime, no ACK-gate, host-side
orchestrator).

Absorbed from tmr:
- #1304 Add early-dispatch for require_sync_start SPMD cohorts, incl. the
  drain_stage_cores parallel-drain refactor (handle_drain_mode two-stage).
- #1326 Defer early dispatch until producer publication (correctness/race):
  published_block_count + record_published_blocks; propagate_dispatch_fanin is
  gated on published_block_count >= logical_block_num; the published_list ledger
  in dispatch and the stage_consumer_blocks two-sided publication/release
  handshake.
- #1328 Shrink dispatch cold-write cost via a folded-gate src_payload
  (PTO2DispatchPayload: not_ready -> volatile uint64_t src_payload, 0 = ready,
  non-zero = gated source PTO2TaskPayload address; global_context to the tail;
  the PTO2_TASKPAYLOAD_*_OFFSET constants + static_asserts). build_payload writes
  args on the ready path and only src_payload on the gated path; the idle AICore
  fills args[] from src_payload during its doorbell wait; init-time prefill of
  async_ctx slab pointers/capacity + context-ptr args; deferred_slab reset moved
  off the dispatch path; software-pipelined prefetch of the next block.
- #1329 Make early-dispatch doorbell ownership exclusive (correctness).
- #1331 Serialize block range claims (correctness): every block-range claim now
  goes through slot_state->claim_block_range(...) instead of an inline
  next_block_idx CAS.

Preserved host-orch divergences (not overwritten by tmr): PTO2_MAX_RING_DEPTH==1
with rings[]/ring_id removed; no advance_ring_pointers / reset_for_reuse /
check_and_handle_consumed (completion via completed_tasks_, consumer wait keys on
fanout_refcount); flat runtime->workers / runtime->func_id_to_addr_ (not
runtime->dev.*); pto_runtime2_types.h keeps its dropped pto2_dispatch_payload.h
include; hbg's AICore FIN-vs-swimlane-record ordering and its no-ACK-gate
completion path (drains via completion-before-dispatch + backstop flushes); no
device orchestrator (orchestrator_done_ absent, scheduler threads gate on
runtime_init_ready_).

Out of scope (unrelated tmr changes hbg still lacks, tracked for a follow-up):
per-device scheduler timeout (get_scheduler_timeout_ms), PTO2_TENSOR_DATA_TIMEOUT
MS-vs-cycles (#1189), stall sub-classification (#1182), runtime scope_tasks_cap
(#1188).

Verified: all 8 runtime targets build -Werror; a2a3sim host_build_graph scene
suite 10/10; a2a3 onboard host_build_graph suite 10 passed / 1 skipped
(paged_attention exercises the new claim_block_range serialization, drain_stage_cores
drain, src_payload gated arg-fill, and published-block gating). tensormap_and_ringbuffer
and the a5 runtimes are untouched.
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