a5 host_build_graph: shrink ready-queue capacity 65536 -> 8192 + graph_ready safe-fail - #1773
Conversation
…h_ready safe-fail Mirror of hw-native-sys#1762 for a5. a5 gained Graph execution in hw-native-sys#1733, which also copied a2a3's pre-hw-native-sys#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 hw-native-sys#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-hw-native-sys#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 hw-native-sys#1733, so no enum change is needed here. Co-Authored-By: Claude <noreply@anthropic.com>
📝 WalkthroughWalkthroughThe PR reduces ChangesReady Queue Overflow Handling
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h`:
- Around line 96-102: Update the PTO2_READY_QUEUE_SIZE comment to explicitly
include graph_ready_queue and graph_prepare_queue alongside the ready, sync, and
dummy queues. Document that overflow from insertion into all named ready, sync,
dummy, and graph queue paths latches PTO2_ERROR_READY_QUEUE_OVERFLOW.
- Around line 96-102: Synchronize the a5 and a2a3 mirror headers byte-for-byte,
including include guards, comments, and the trailing `#endif`; update the affected
header to exactly match its counterpart while preserving the shared queue
definition and scheduler content.
In `@src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h`:
- Around line 493-505: Update both graph_prepare_queue enqueue paths to detect
push_tagged failure, latch PTO2_ERROR_READY_QUEUE_OVERFLOW, and stop retrying
instead of spinning indefinitely. Match the overflow handling used by
push_ready_routed while preserving the existing successful enqueue behavior.
🪄 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: a43bfa95-0809-41e2-8684-687a4f854f90
📒 Files selected for processing (2)
src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.hsrc/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
| // Per-shape ready-queue capacity (power of two). This is a ring buffer that | ||
| // bounds peak CONCURRENT occupancy (enqueue_pos - dequeue_pos), not total task | ||
| // count: slots recycle, so capacity need only exceed the most tasks ever | ||
| // simultaneously ready in any one queue. Overflow on the ready/sync/dummy queues | ||
| // latches PTO2_ERROR_READY_QUEUE_OVERFLOW (safe-fail), so it must exceed the | ||
| // worst-case ready burst with margin. | ||
| #define PTO2_READY_QUEUE_SIZE 8192 |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Document the graph queues in the capacity contract.
PTO2_READY_QUEUE_SIZE also sizes graph_ready_queue and graph_prepare_queue in src/a5/runtime/host_build_graph/runtime/shared/pto_runtime2_init.cpp:104-124. Lines 99-100 list only ready, sync, and dummy queues. The “per-shape” description also omits graph queues. Name all queues that use this capacity and state which insertion paths latch PTO2_ERROR_READY_QUEUE_OVERFLOW.
🤖 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 96
- 102, Update the PTO2_READY_QUEUE_SIZE comment to explicitly include
graph_ready_queue and graph_prepare_queue alongside the ready, sync, and dummy
queues. Document that overflow from insertion into all named ready, sync, dummy,
and graph queue paths latches PTO2_ERROR_READY_QUEUE_OVERFLOW.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
diff -u \
<(sed -n '96,102p' src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h) \
<(sed -n '96,102p' src/a2a3/runtime/host_build_graph/runtime/pto_runtime2_types.h)
diff -u \
<(sed -n '491,518p' src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h) \
<(sed -n '491,518p' src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h)Repository: hw-native-sys/simpler
Length of output: 247
🏁 Script executed:
#!/bin/bash
set -euo pipefail
for file in \
src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h \
src/a2a3/runtime/host_build_graph/runtime/pto_runtime2_types.h \
src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h \
src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
do
if [ -f "$file" ]; then
echo "FOUND $file"
wc -l "$file"
else
echo "MISSING $file"
fi
done
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
if [ -f src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h ] &&
[ -f src/a2a3/runtime/host_build_graph/runtime/pto_runtime2_types.h ]; then
sed -n '96,102p' src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h > "$tmpdir/a5-types"
sed -n '96,102p' src/a2a3/runtime/host_build_graph/runtime/pto_runtime2_types.h > "$tmpdir/a2a3-types"
diff -u "$tmpdir/a5-types" "$tmpdir/a2a3-types" || true
fi
if [ -f src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h ] &&
[ -f src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h ]; then
sed -n '491,518p' src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h > "$tmpdir/a5-scheduler"
sed -n '491,518p' src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h > "$tmpdir/a2a3-scheduler"
diff -u "$tmpdir/a5-scheduler" "$tmpdir/a2a3-scheduler" || true
fiRepository: hw-native-sys/simpler
Length of output: 1347
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- a5 types ---'
sed -n '90,110p' src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h
echo '--- a2a3 types ---'
sed -n '90,115p' src/a2a3/runtime/host_build_graph/runtime/pto_runtime2_types.h
echo '--- a5 scheduler ---'
sed -n '485,525p' src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
echo '--- a2a3 scheduler ---'
sed -n '485,525p' src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
echo '--- exact scheduler-region comparison ---'
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
sed -n '491,518p' src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h > "$tmpdir/a5"
sed -n '491,518p' src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h > "$tmpdir/a2a3"
cmp -s "$tmpdir/a5" "$tmpdir/a2a3" && echo IDENTICAL || echo DIFFERENTRepository: hw-native-sys/simpler
Length of output: 7266
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
from difflib import unified_diff
a5 = Path("src/a5/runtime/host_build_graph/runtime/pto_runtime2_types.h").read_text()
a2a3 = Path("src/a2a3/runtime/host_build_graph/runtime/pto_runtime2_types.h").read_text()
print("--- header diff ---")
for line in unified_diff(
a2a3.splitlines(True),
a5.splitlines(True),
fromfile="a2a3",
tofile="a5",
):
print(line, end="")
print("--- queue definitions ---")
for name, text in [("a5", a5), ("a2a3", a2a3)]:
lines = text.splitlines()
matches = [f"{i+1}: {line}" for i, line in enumerate(lines)
if "PTO2_READY_QUEUE_SIZE" in line]
print(name)
print("\n".join(matches))
s5 = Path("src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h").read_bytes()
s2 = Path("src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h").read_bytes()
print("--- scheduler equality ---")
print("full files identical:", s5 == s2)
print("region 491-518 identical:",
Path("src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h").read_text().splitlines()[490:518] ==
Path("src/a2a3/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h").read_text().splitlines()[490:518])
PY
echo '--- queue-capacity usages ---'
rg -n -C 3 'PTO2_READY_QUEUE_SIZE|ready_sync_queues|dummy_ready_queue|graph_ready_queue|READY_QUEUE_OVERFLOW' \
src/a5/runtime/host_build_graph/runtime \
src/a2a3/runtime/host_build_graph/runtimeRepository: hw-native-sys/simpler
Length of output: 50377
Keep the a5 and a2a3 mirror headers byte-for-byte identical.
The queue definition and scheduler region match. The headers still differ in include guards, comments, and trailing #endif; these files are not documented exceptions.
🤖 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 96
- 102, Synchronize the a5 and a2a3 mirror headers byte-for-byte, including
include guards, comments, and the trailing `#endif`; update the affected header to
exactly match its counterpart while preserving the shared queue definition and
scheduler content.
Source: Learnings
| if (slot_state->task_kind == TaskKind::GRAPH) { | ||
| pushed = graph_ready_queue.push(slot_state); | ||
| } else { | ||
| pushed = ready_queues[static_cast<int32_t>(shape)].push(slot_state); | ||
| PTO2ResourceShape shape = slot_state->active_mask.to_shape(); | ||
| if (shape == PTO2ResourceShape::DUMMY || | ||
| (slot_state->task_attrs.has_predicate() && !slot_state->payload->predicate.pass())) { | ||
| pushed = dummy_ready_queue.push(slot_state); | ||
| } else if (slot_state->task_attrs.requires_sync_start()) { | ||
| pushed = ready_sync_queues[static_cast<int32_t>(shape)].push(slot_state); | ||
| } else { | ||
| pushed = ready_queues[static_cast<int32_t>(shape)].push(slot_state); | ||
| } | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -u
rg -n -C 8 -P '\bgraph_prepare_queue\b' src/a5/runtime/host_build_graphRepository: hw-native-sys/simpler
Length of output: 16999
🏁 Script executed:
#!/bin/bash
set -u
printf '%s\n' '--- queue implementation and error constants ---'
rg -n -C 10 'struct PTO2ReadyQueue|class PTO2ReadyQueue|bool push|push_tagged|PTO2_ERROR_READY_QUEUE_OVERFLOW|ready_queue_capacity' \
src/a5/runtime/host_build_graph/runtime
printf '%s\n' '--- graph preparation call sites ---'
rg -n -C 14 'graph_prepare_queue\.(push|push_tagged)|while \(!sched_->graph_prepare_queue' \
src/a5/runtime/host_build_graph/runtime
printf '%s\n' '--- scheduler error consumption and queue sizing ---'
rg -n -C 8 'sched_error_code|PTO2_READY_QUEUE_SIZE|off_graph_prepare_queue_slots|ready_queue_capacity' \
src/a5/runtime/host_build_graph/runtime/scheduler \
src/a5/runtime/host_build_graph/runtime/sharedRepository: hw-native-sys/simpler
Length of output: 50377
🏁 Script executed:
#!/bin/bash
set -u
printf '%s\n' '--- PTO2ReadyQueue push semantics ---'
sed -n '63,152p' src/a5/runtime/host_build_graph/runtime/scheduler/pto_scheduler.h
printf '%s\n' '--- graph preparation control flow ---'
sed -n '1118,1160p' src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_cold_path.cpp
sed -n '1288,1365p' src/a5/runtime/host_build_graph/runtime/scheduler/scheduler_dispatch.cpp
printf '%s\n' '--- queue consumers and scheduler stop behavior ---'
rg -n -C 6 'graph_prepare_queue\.pop|sched_error_code\.load|completed_\.load|PTO2_ERROR_READY_QUEUE_OVERFLOW' \
src/a5/runtime/host_build_graph/runtime/schedulerRepository: hw-native-sys/simpler
Length of output: 26385
Retain the overflow-handling concern for graph_prepare_queue.
Both graph_prepare_queue enqueue paths retry until push_tagged succeeds, but neither path latches PTO2_ERROR_READY_QUEUE_OVERFLOW. A full queue therefore causes an unbounded spin rather than the error handling used by push_ready_routed.
🤖 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 493 - 505, Update both graph_prepare_queue enqueue paths to detect
push_tagged failure, latch PTO2_ERROR_READY_QUEUE_OVERFLOW, and stop retrying
instead of spinning indefinitely. Match the overflow handling used by
push_ready_routed while preserving the existing successful enqueue behavior.
a5 host_build_graph: ready-queue capacity 65536 -> 8192 + graph_ready safe-fail
a5 mirror of #1762 (which was a2a3-only). a5's Graph execution landed in #1733,
which copied a2a3's pre-#1762
push_ready_routed— including the graph_readypush that ignored its return value. This PR applies the same two changes #1762
landed for a2a3.
Changes
PTO2_READY_QUEUE_SIZE65536 -> 8192 (same rationale as [Performance] host_build_graph: shrink ready-queue capacity 65536 -> 8192 #1762: the Vyukovring bounds is peak concurrent occupancy, not total task count).
push_ready_routed: the GRAPH task now goes through the checked push, so afull graph_ready_queue latches
PTO2_ERROR_READY_QUEUE_OVERFLOWinstead ofsilently dropping the task.
a5's
push_ready_routedwas byte-identical to a2a3 pre-#1762; this is a 1:1mirror and the two changed regions are now identical across a2a3 and a5.
PTO2_ERROR_READY_QUEUE_OVERFLOW 104was already added to a5's error enum by#1733, so no enum change is needed.
Verification
graph_execution(3) +paged_attention(1) — 4 passed.Caveat
a5 has no independent peak-occupancy measurement — the same gap #1762 noted
when it deferred a5. The safe-fail now covers graph_ready too, so an undersized
cap surfaces as
READY_QUEUE_OVERFLOW(named emergency_shutdown) rather thansilent corruption or a hang. a5 onboard occupancy measurement remains a
separate follow-up, matching how #1762 treated a5.