Skip to content

perf(l2-swimlane): capture orchestrator phase records per-scope (depth<=1), a2a3 + a5 (Swimlane L4 in-window overhead ~9% -> ~0%) - #1382

Closed
noabauma wants to merge 1 commit into
hw-native-sys:mainfrom
huawei-csl:perf/swimlane-orch-per-scope
Closed

perf(l2-swimlane): capture orchestrator phase records per-scope (depth<=1), a2a3 + a5 (Swimlane L4 in-window overhead ~9% -> ~0%)#1382
noabauma wants to merge 1 commit into
hw-native-sys:mainfrom
huawei-csl:perf/swimlane-orch-per-scope

Conversation

@noabauma

@noabauma noabauma commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

L4 swimlane recorded one orchestrator phase span per submit_task() /
alloc_tensors(), putting a per-task write on the orchestrator critical path
(~+9% in-window overhead on paged_attention). This records instead one span
per orchestration scope at nesting depth ≤ 1
. Nearly all scopes nest deeper,
so this keeps the top-level phase structure while cutting the in-window overhead
to ≈0%.

The per-submit record path (CYCLE_COUNT_ORCH_SUBMIT_RECORD and its
g_orch_submit_idx / _submit_start_ts scaffolding) is removed outright,
not left as a no-op. Applied identically to the a2a3 and a5
tensormap_and_ringbuffer orchestrators. The per-sub-step cumulative counters
(g_orch_*_cycle) are unaffected.

Benchmark (a2a3, in-window .orch, vs --enable-l2-swimlane-off idle)

workload before (per-submit) after (per-scope depth≤1)
paged_attention Case2 +9.6% ≈0% (−0.9%, noise)
paged_attention Case1 +7.7% ≈0%
pa_manual_scope +7.5% ≈0%
qwen3_14b_decode +6.5% ≈0%

The win scales with how deeply a workload nests its scopes (near-total on the
big attention/decode kernels, negligible-but-harmless on trivial ones). With the
per-submit record fully removed, Case2 L4 is now within noise of idle.

STRACE device windows — Case2, --rounds 1, median of 10 runs (devices 4–7)

window (µs, median of 10) main L4-off main L4-on branch L4-off branch L4-on
device_wall (depth 2) 24690 26454 24067 24084
graph_build (depth 3) 24623 26242 24005 23877
orch (depth 3) 24363 25962 23753 23560
sched (depth 3) 24461 26056 23839 23690

Enabling L4 inflates the orchestration window ~6.6% and the whole device run
~7% on main; on this branch it stays within noise (~0%) across all windows.

Trade-off

Orchestrator capture is now always per-scope depth≤1 — the previous per-task
(deeper-scope) orch detail is no longer produced. That detail was the source of
the overhead and is rarely used; the depth constant (kOrchPhaseScopeDepth) is
a one-line bump if a workload ever needs it, and a static_assert bounds the cap
within g_orch_scope_start_ts.

Testing

  • Compiles for a2a3 + a5 across all profiling-flags-smoke combos
    (SIMPLER_DFX=0, SIMPLER_ORCH_PROFILING, SIMPLER_SCHED_PROFILING,
    SIMPLER_TENSORMAP_PROFILING, and their unions).
  • a5sim: l2_swimlane scene test passes (a5 orch-phase path exercised).
  • a2a3 onboard: paged_attention passes at all levels; Case2 idle→L4 ≈ 0%
    in-window.
  • Rebased onto current main; st-onboard-a5 exercises the a5 path on real
    silicon in CI.

@coderabbitai

coderabbitai Bot commented Jul 16, 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: 8d40bab0-dbc2-42bc-afec-445655cddc93

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

Adds host-configured orchestrator scope depth to shared-memory initialization, supports per-scope timing records in profiling and DFX paths, and documents measurements leading to a depth-limited capture policy.

Changes

Orchestrator scope profiling

Layer / File(s) Summary
Scope-depth configuration wiring
src/common/platform/include/common/l2_swimlane_profiling.h, src/common/platform/shared/host/..., src/common/platform/shared/aicpu/..., src/common/platform/include/aicpu/..., src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.h, src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp
Adds orch_phase_scope_depth to the shared header and runtime state, initializes it from SIMPLER_ORCH_PHASE_SCOPE_DEPTH, and passes it into the AICPU executor.
Scope-based orchestration recording
src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp
Captures scope timestamps, emits per-scope records, suppresses per-submit records in scope mode, and resets the scope record index.
Overhead investigation and adopted policy
docs/investigations/2026-07-l2-swimlane-orch-overhead-tracr-defer.md, docs/investigations/README.md
Documents benchmark results, evaluated mitigation strategies, the adopted depth limit, and the investigation index entry.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Host
  participant SharedHeader
  participant AICPU
  participant Orchestrator
  participant Recorder
  Host->>SharedHeader: Set orch_phase_scope_depth
  SharedHeader->>AICPU: Initialize scope-depth configuration
  AICPU->>Orchestrator: Provide configured depth
  Orchestrator->>Recorder: Emit scope timing record
Loading

Poem

A rabbit hops through scopes so neat,
With timestamps tucked beneath its feet.
Fewer records cross the lane,
Depth-limited hops ease the strain.
The swimlane hums, the buffers cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 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.
Title check ✅ Passed The title clearly summarizes the main change: per-scope orchestrator phase capture to cut L4 overhead.
Description check ✅ Passed The description directly matches the changeset and explains the runtime depth-limited capture and overhead impact.

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 gemini-code-assist 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.

Code Review

This pull request introduces a runtime-configurable orchestrator phase-record granularity (orch_phase_scope_depth) to mitigate L2 swimlane L4 orchestrator overhead, implementing a depth-limit approach based on performance investigations. Feedback on the changes highlights potential out-of-bounds write and read vulnerabilities in pto_orchestrator.cpp when indexing g_orch_scope_start_ts with orch->scope_stack_top in begin_scope and end_scope, and recommends adding defensive bounds checks against PTO2_MAX_SCOPE_DEPTH.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp Outdated
Comment thread src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp Outdated

@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: 5

🤖 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/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp`:
- Around line 675-684: The orchestration phase recording in
l2_swimlane_aicpu_record_orch_phase passes scope_stack_top as an unencoded
task_id, violating the PTO2 cross-view correlation contract. Update this
scope-record path to use a distinct, full PTO2 encoding with the appropriate
ring identifier and local scope value, or route scopes through a dedicated API;
ensure downstream parsing can distinguish scope records from task records.
- Around line 621-626: Align all accesses to the DFX-only fields
orch_phase_scope_depth and l2_swimlane_level with SIMPLER_DFX: update the guards
around the scope-start logic at
src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp lines
621-626 and 675-684, guard the orch_phase_scope_depth access at line 147, and
ensure CYCLE_COUNT_START and CYCLE_COUNT_ORCH_SUBMIT_RECORD at lines 157-169
only evaluate these fields under SIMPLER_DFX.

In `@src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.h`:
- Around line 101-103: Remove the configurable orch_phase_scope_depth knob and
its associated SIMPLER_ORCH_PHASE_SCOPE_DEPTH environment-variable and
get_orch_phase_scope_depth() plumbing. Define and use a fixed constant such as
kOrchPhaseMaxDepth = 1 in the orchestration phase-scope logic, preserving
per-submit behavior only where the hardcoded depth condition requires it.

In `@src/common/platform/shared/aicpu/l2_swimlane_collector_aicpu.cpp`:
- Line 280: Reset g_orch_phase_scope_depth to -1 alongside the other
launch-state resets before checking g_platform_l2_swimlane_base. Preserve the
existing header assignment afterward so a valid s_l2_swimlane_header overwrites
the reset value.

In `@src/common/platform/shared/host/l2_swimlane_collector.cpp`:
- Around line 214-217: Replace the unchecked std::atoi parsing of
SIMPLER_ORCH_PHASE_SCOPE_DEPTH in the orchestrator phase-depth initialization
with checked parsing that requires the entire value to be a valid signed integer
within int32_t range. Preserve -1 as the default and for invalid input, or fail
initialization with a clear diagnostic; do not allow malformed values to become
depth 0.
🪄 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

Run ID: 820b956a-436e-4ec8-9997-64ea82b72c61

📥 Commits

Reviewing files that changed from the base of the PR and between 172aec1 and 5764412.

📒 Files selected for processing (9)
  • docs/investigations/2026-07-l2-swimlane-orch-overhead-tracr-defer.md
  • docs/investigations/README.md
  • src/a2a3/runtime/tensormap_and_ringbuffer/aicpu/aicpu_executor.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.h
  • src/common/platform/include/aicpu/l2_swimlane_collector_aicpu.h
  • src/common/platform/include/common/l2_swimlane_profiling.h
  • src/common/platform/shared/aicpu/l2_swimlane_collector_aicpu.cpp
  • src/common/platform/shared/host/l2_swimlane_collector.cpp

Comment thread src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp Outdated
Comment thread src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp Outdated
Comment thread src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.h Outdated
Comment thread src/common/platform/shared/aicpu/l2_swimlane_collector_aicpu.cpp Outdated
Comment thread src/common/platform/shared/host/l2_swimlane_collector.cpp Outdated
@noabauma noabauma changed the title perf(a2a3/l2-swimlane): runtime-selectable orchestrator phase-record granularity (SIMPLER_ORCH_PHASE_SCOPE_DEPTH) perf(a2a3/l2-swimlane): runtime-selectable orchestrator phase-record granularity (Making Swimlane L4 effectively zero cost during scheduling!) Jul 20, 2026
@noabauma
noabauma force-pushed the perf/swimlane-orch-per-scope branch from 81805d9 to 3c0eb46 Compare July 20, 2026 09:44
@noabauma noabauma changed the title perf(a2a3/l2-swimlane): runtime-selectable orchestrator phase-record granularity (Making Swimlane L4 effectively zero cost during scheduling!) perf(a2a3/l2-swimlane): capture orchestrator phase records per-scope (depth<=1) (Reducing Swimlane L4 overhead from ~9% -> ~0% during scheduling!) Jul 20, 2026
@noabauma

noabauma commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

The CI is failing due to a mismatch in the golden score. Nothing which this PR is even touching...

Please rerun it.

@noabauma
noabauma force-pushed the perf/swimlane-orch-per-scope branch from 3c0eb46 to 89474eb Compare July 20, 2026 14:07
@noabauma noabauma closed this Jul 21, 2026
@noabauma noabauma reopened this Jul 21, 2026
…a3 + a5)

L4 orchestrator profiling recorded one swim-lane span per submit_task() /
alloc_tensors(), which put a per-task write on the orchestrator critical path
(~+9% in-window on paged_attention). Record instead one span per orchestration
scope at nesting depth <= 1: nearly all scopes nest deeper, so this keeps the
top-level phase structure while cutting the in-window overhead to ~0% (Case2:
+9.6% -> +1.3%, measured a2a3). The per-sub-step cumulative counters are
unaffected.

The per-submit record path (CYCLE_COUNT_ORCH_SUBMIT_RECORD and its
g_orch_submit_idx / _submit_start_ts scaffolding) is removed outright rather
than left as a no-op. The scope hooks read l2_swimlane_level, a SIMPLER_DFX-only
field, so they are guarded with SIMPLER_DFX; a static_assert bounds the depth cap
within g_orch_scope_start_ts.

Applied identically to the a2a3 and a5 tensormap_and_ringbuffer orchestrators.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@noabauma
noabauma force-pushed the perf/swimlane-orch-per-scope branch from 89474eb to 04b352d Compare July 21, 2026 08:39
@noabauma noabauma changed the title perf(a2a3/l2-swimlane): capture orchestrator phase records per-scope (depth<=1) (Reducing Swimlane L4 overhead from ~9% -> ~0% during scheduling!) perf(l2-swimlane): capture orchestrator phase records per-scope (depth<=1), a2a3 + a5 (Swimlane L4 in-window overhead ~9% -> ~0%) Jul 21, 2026
@ChaoZheng109

Copy link
Copy Markdown
Collaborator

Concern: this trades away a DFX capability to shave an overhead that a lower profiling level already avoids.

The ~9% in-window cost this PR targets is exclusive to the top profiling level (ORCH_PHASES). The orchestrator-record emit — including the timestamp sampling — is gated on l2_swimlane_level >= L2SwimlaneLevel::ORCH_PHASES, so at any lower level the orchestrator critical path already pays zero, while still retaining full per-task AICore/AICPU timing and the scheduler-phase breakdown. Anyone who wants the run without the orchestrator-capture overhead can already get it, with no code change, by selecting a lower --enable-l2-swimlane level.

What this change gives up in exchange is not free: it removes the per-task submit-timing granularity. Previously each submit_task() / alloc_tensors() emitted one orchestrator envelope [start, end] carrying the real task_id.raw, which the swimlane renders as a per-task orchestrator bar. After this change the orchestrator view collapses to a per-scope (depth <= 1) envelope with no per-task identity — a permanent reduction in what our DFX tooling can show at the deepest profiling level. The orchestrator-side per-task detail was precisely what this level added over the lower ones, and that is what is being dropped.

The net effect is a worse trade on both ends: to lower overhead, a lower profiling level already achieves zero cost with no loss elsewhere; to keep per-task orchestrator detail, the pre-change behavior is required. The post-change top level only offers a coarse per-scope overview in between, at the cost of permanently reducing our DFX capture granularity — so this optimization is not worth the capability we lose for it.

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.

2 participants