Refactor: separate A2/A3 device launch and reap#1462
Conversation
📝 WalkthroughWalkthroughThe PR replaces drain-based orchestration with per-run lifecycle APIs, introduces asynchronous Python ChangesRun lifecycle and completion fencing
Device runner phase separation
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant Caller
participant Worker
participant RunHandle
participant Orchestrator
participant Scheduler
Caller->>Worker: submit(callable)
Worker->>Orchestrator: begin_run()
Worker->>Orchestrator: close_run_submission(run_id)
Scheduler->>Orchestrator: report_task_error(slot, message)
Caller->>RunHandle: wait()
RunHandle->>Orchestrator: wait_run(run_id)
RunHandle->>Worker: finalize run cleanup
Worker->>Orchestrator: release_run(run_id)
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/a2a3/platform/onboard/host/device_runner.cpp (1)
475-492: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winFinalize
dep_genon launch failures too.
launch_runreturns on AICore/AICPU launch failures beforereap_run()runs, so the sync-error/path that already callsteardown_shared_collectors_after_run()bypasses thedep_gen_collector_.stop()+ counter reconciliation +deps.jsonreplay. Add an idempotent per-run terminal cleanup helper and invoke it from both launch-error returns and the success path to avoid emitting twice.🤖 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/a2a3/platform/onboard/host/device_runner.cpp` around lines 475 - 492, Add an idempotent per-run terminal cleanup helper that stops dep_gen collection, reconciles its counters, and replays deps.json, then invoke it from both AICore/AICPU launch-failure returns in launch_run and the existing successful reap_run path. Ensure the helper coordinates with teardown_shared_collectors_after_run() and prevents duplicate emission during the same run.
🧹 Nitpick comments (2)
python/simpler/worker.py (2)
5840-5847: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSecondary cleanup errors in
_finalize_run_handleare silently dropped.
_step()only records the first exception intoresult; any later step's exception (onceresultis already set) is swallowed with no diagnostic at all — unlike other best-effort cleanup helpers in this file (e.g._flush_pending_remote_frees,_release_all_live_domains) which write the dropped errors tostderr. Worth at least astderrnote for observability parity.🤖 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 `@python/simpler/worker.py` around lines 5840 - 5847, The exception path in _finalize_run_handle’s nested _step should report subsequent cleanup failures when result is already set. Preserve the first exception in result, but write later exceptions to stderr, matching the diagnostic behavior of _flush_pending_remote_frees and _release_all_live_domains.
5738-5821: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
callableshadows the Python builtin across the new submit/run API and its tests. The newWorker.submit/run/_submit_locked/_submit_l3_lockedmethods name their callback parametercallable, which Ruff flags (A002); the pattern is then echoed in test doubles/locals.
python/simpler/worker.py#L5738-L5821: rename thecallableparameter (e.g.orch_fn/fn) insubmit,run,_submit_locked, and_submit_l3_locked.tests/ut/py/test_worker/test_host_worker.py#L1568-L1587: renamefake_submit'scallableparameter to match the renamed API.tests/ut/py/test_worker/test_startup_readiness.py#L764-L777: rename the local variablecallableintest_l2_submit_returns_completed_handle.🤖 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 `@python/simpler/worker.py` around lines 5738 - 5821, Rename the callable parameter in Worker.submit, run, _submit_locked, and _submit_l3_locked to a non-shadowing name, updating all internal references and preserving behavior. Also rename the callable parameter in tests/ut/py/test_worker/test_host_worker.py lines 1568-1587 and the local callable variable in tests/ut/py/test_worker/test_startup_readiness.py lines 764-777; no other changes are needed.Source: Linters/SAST tools
🤖 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/orchestrator.md`:
- Around line 54-61: Update docs/orchestrator.md lines 54-61 to document
fail_run_submission(RunId run_id) without the exception_ptr parameter, matching
the binding contract. Also update docs/orchestrator.md lines 193-195 so the
pseudocode calls tensormap_.lookup(current_run_id, key) and
tensormap_.insert(current_run_id, key, sid), preserving the documented
run-scoped TensorMap API.
In `@python/simpler/worker.py`:
- Around line 1921-1968: Protect the `_finalize_run_handle` call in
`RunHandle.wait()` so any `BaseException` during finalization still records
terminal state, clears `_wait_in_progress`, releases run resources, notifies
waiters, and preserves the exception as the handle error. Ensure the
terminal-state assignments occur before any condition-variable acquisition,
mirroring the `Worker.close()` stranded-joiner protection, while retaining
normal native-error propagation.
In `@src/a2a3/platform/onboard/host/device_runner.h`:
- Around line 222-225: Update the public run() documentation to describe the
actual launch order: AICore submission via launch_run() occurs before AICPU
submission. Keep the surrounding synchronization and teardown documentation
unchanged.
In `@src/common/hierarchical/orchestrator.cpp`:
- Around line 204-207: Update Orchestrator::report_task_error to check
task.run_id before calling record_run_error: return safely when it equals
INVALID_RUN_ID, and handle or explicitly preserve the live-run assumption so an
unknown run id cannot unwind the scheduler loop. Keep normal error recording
unchanged for valid, existing run ids.
In `@tests/ut/cpp/hierarchical/test_tensormap.cpp`:
- Around line 105-117: Update TensorMap output cleanup to accept the producing
slot and erase a key only when its current mapping for the run still points to
that slot, preserving newer same-run producers. Modify the cleanup call sites
and the relevant TensorMap method, then extend SameAddressIsNamespacedByRun with
a same-run write-after-write regression covering producer overwrite and
subsequent cleanup.
---
Outside diff comments:
In `@src/a2a3/platform/onboard/host/device_runner.cpp`:
- Around line 475-492: Add an idempotent per-run terminal cleanup helper that
stops dep_gen collection, reconciles its counters, and replays deps.json, then
invoke it from both AICore/AICPU launch-failure returns in launch_run and the
existing successful reap_run path. Ensure the helper coordinates with
teardown_shared_collectors_after_run() and prevents duplicate emission during
the same run.
---
Nitpick comments:
In `@python/simpler/worker.py`:
- Around line 5840-5847: The exception path in _finalize_run_handle’s nested
_step should report subsequent cleanup failures when result is already set.
Preserve the first exception in result, but write later exceptions to stderr,
matching the diagnostic behavior of _flush_pending_remote_frees and
_release_all_live_domains.
- Around line 5738-5821: Rename the callable parameter in Worker.submit, run,
_submit_locked, and _submit_l3_locked to a non-shadowing name, updating all
internal references and preserving behavior. Also rename the callable parameter
in tests/ut/py/test_worker/test_host_worker.py lines 1568-1587 and the local
callable variable in tests/ut/py/test_worker/test_startup_readiness.py lines
764-777; no other changes are needed.
🪄 Autofix (Beta)
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: b5f4444d-ede8-4a58-91a7-0c0106dcf340
📒 Files selected for processing (32)
docs/comm-domain.mddocs/hierarchical_level_runtime.mddocs/orchestrator.mddocs/remote-l3-worker-design.mddocs/scheduler.mddocs/task-flow.mdpython/bindings/worker_bind.hpython/simpler/orchestrator.pypython/simpler/task_interface.pypython/simpler/worker.pysrc/a2a3/platform/onboard/host/device_runner.cppsrc/a2a3/platform/onboard/host/device_runner.hsrc/common/hierarchical/orchestrator.cppsrc/common/hierarchical/orchestrator.hsrc/common/hierarchical/ring.cppsrc/common/hierarchical/ring.hsrc/common/hierarchical/scheduler.cppsrc/common/hierarchical/scheduler.hsrc/common/hierarchical/tensormap.cppsrc/common/hierarchical/tensormap.hsrc/common/hierarchical/types.cppsrc/common/hierarchical/types.hsrc/common/hierarchical/worker.cppsrc/common/hierarchical/worker_manager.cppsrc/common/hierarchical/worker_manager.htests/ut/cpp/hierarchical/test_orchestrator.cpptests/ut/cpp/hierarchical/test_scheduler.cpptests/ut/cpp/hierarchical/test_tensormap.cpptests/ut/py/test_worker/test_error_propagation.pytests/ut/py/test_worker/test_host_worker.pytests/ut/py/test_worker/test_l3_l2_orch_comm.pytests/ut/py/test_worker/test_startup_readiness.py
0aec39c to
a704a1b
Compare
a704a1b to
015d4e7
Compare
bebbfaf to
bdba7bc
Compare
Split the A2/A3 onboard DeviceRunner::run() kernel submission boundary into launch_run(), and move stream synchronization, device-error recovery, profiling export and timing collection into reap_run(). run() stays strictly synchronous as launch_run() followed immediately by reap_run(). The effective statement sequence, every error return code and every recovery action are unchanged, including the collector teardown on the sync-failure path and print_handshake_results() on the success path only. reap_run() takes no arguments and reads only members, so a later change can defer it without re-splitting its inputs. Correct the run() step list, which named the AICPU kernel before the AICore kernel while the launch has submitted AICore first. No ACK states, resource banks, background reaping, or execution overlap are added here.
Summary
DeviceRunner::run()kernel submission boundary intolaunch_run()reap_run()run()strictly synchronous aslaunch_run()followed immediately byreap_run()run()step list, which named the AICPU kernel before the AICore kernel while the launch has submitted AICore firstThis is behavior-equivalent groundwork: the effective statement sequence, every
error return code, and every recovery action are unchanged — including the
collector teardown on the sync-failure path and
print_handshake_results()onthe success path only.
reap_run()deliberately takes no arguments and readsonly members, so a later change can defer it without re-splitting its inputs.
Series context
Part of the worker async-preparation series, following #1459 (per-run identity
and completion fence) and #1460 (
Worker.submitand run handles), both merged.Asynchronous reaping, resource banks and device overlap come later.
Validation
libhost_runtime.sorebuilt for bothhost_build_graphandtensormap_and_ringbuffer— the real compile check, since this code isonboard-only
Neither unit-test suite exercises the onboard
DeviceRunnerpath, so theonboard CI job is the meaningful check. The A2/A3 hardware runs quoted in
earlier revisions were against a commit that is no longer in this branch's
history and have not been re-run.