Skip to content

Fix: split A5 L2 record reserve and commit - #1603

Open
yanghaoran29 wants to merge 1 commit into
hw-native-sys:mainfrom
yanghaoran29:perf/a5-l2-reserve-commit
Open

Fix: split A5 L2 record reserve and commit#1603
yanghaoran29 wants to merge 1 commit into
hw-native-sys:mainfrom
yanghaoran29:perf/a5-l2-reserve-commit

Conversation

@yanghaoran29

@yanghaoran29 yanghaoran29 commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • reserve the A5 L2 task-record slot before ACK and commit that exact slot after execution, so buffer rotation cannot move a record into a later generation
  • avoid reading the AICore system timer when L2 swimlane DFX is disabled
  • preserve A5 PMU per-task staging order and lazy L2 head resolution
  • add a focused unit test for reserve/commit across buffer generation changes

Related to #1582 (missing item #5).

Correctness

The reserved L2 record remains bound to the buffer generation that was active before ACK. PMU data is still published before FIN for AICPU consumption, while the L2 record is committed after FIN using the reserved pointer.

Validation

  • pre-commit on all changed files: passed
  • focused C++ generation test: passed
  • A5Sim L2-only, level 4 + dep-gen: 2 passed
  • A5Sim PMU-only: 1 passed
  • A5Sim L2 + PMU, level 4: 2 passed
  • A5Sim DFX-off vector smoke: 1 passed
  • A5 onboard L2 + PMU, level 4 + dep-gen: 2 passed
  • full A5Sim tensor-map/ring-buffer suite: 72 passed, 2 skipped; 3 timing-marker tests failed in the sweep and passed when rerun in isolation (existing capture flake, outside this L2 path)

Performance (--enable-l2-swimlane 4)

Same main commit (ce81c973), device 4, serial execution. Each variant used 10 independent processes with --rounds 1 --enable-l2-swimlane 4, because the scene-test runner disables L2 swimlane when --rounds is greater than 1. All 40 valid case runs per variant passed.

Device is the complete on-NPU AICPU run_prepared.runner_run.device_wall span emitted by [STRACE]; it excludes Python startup and host-side swimlane export/validation. Values below are arithmetic means over the 10 independent runs:

mean Device = sum(Device for 10 runs) / 10
delta = (PR mean - main mean) / main mean * 100%

A negative delta means the PR is faster. For example, paged-attention Case1 is (2457.97 - 2467.15) / 2467.15 = -0.37%.

Case Metric main mean this PR mean delta
paged_attention_unroll / Case1 Device 2467.15 us 2457.97 us -0.37%
paged_attention_unroll / Case1 Effective 2050.99 us 2054.23 us +0.16%
paged_attention_unroll / Case2 Device 1526.57 us 1523.77 us -0.18%
paged_attention_unroll / Case2 Effective 1109.29 us 1106.36 us -0.26%
manual_scope / Case1 Device 2461.55 us 2406.86 us -2.22%
manual_scope / Case1 Effective 2017.20 us 1968.11 us -2.43%
manual_scope / Case2 Device 1506.94 us 1507.77 us +0.06%
manual_scope / Case2 Effective 1075.78 us 1079.31 us +0.33%

No level-4 performance regression observed; three cases are effectively flat and manual-scope Case1 improves by about 2.2%-2.4%.

@coderabbitai

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

Run ID: 5918decf-306b-4e9d-9820-8aedfa5a6b9a

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

AICore execution now conditionally captures L2 swimlane timing, reserves task records before ACK publication, and commits them after completion. A no-hardware unit test and CTest target validate reserved buffer generation behavior.

Changes

AICore L2 swimlane recording

Layer / File(s) Summary
Executor reservation and commit flow
src/a5/runtime/tensormap_and_ringbuffer/aicore/aicore_executor.cpp
Timing capture is gated by L2 swimlane profiling; task records are reserved before ACK publication and committed after execution using the reserved handle.
Reserved record generation validation
tests/ut/cpp/common/test_l2_swimlane_aicore.cpp, tests/ut/cpp/CMakeLists.txt
A no-hardware GoogleTest verifies commits target the reserved buffer generation, and CTest builds and registers the new test.

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

Possibly related PRs

Poem

A bunny watched the records hop,
Reserved before the ACK could stop.
Timings gathered, then committed tight,
Each buffer kept its proper flight.
Test carrots prove the generations right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly and concisely describes the main change: separating A5 L2 record reservation from commit.
Description check ✅ Passed The description directly explains the implementation, rationale, tests, and performance validation for the changeset.

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.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/a5/runtime/tensormap_and_ringbuffer/aicore/aicore_executor.cpp (1)

235-250: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Commit the reserved L2 record before publishing FIN.

MAKE_FIN_VALUE(task_id) makes completion visible before l2_swimlane_aicore_commit_task_record writes the record. The completion consumer can therefore observe an uncommitted/partial L2 entry. Commit after execution but before FIN.

Proposed ordering fix
-            last_reg_val = reg_val;
-            write_reg(RegId::COND, MAKE_FIN_VALUE(task_id));
-
-            if (dump_args_enabled) {
-                pipe_barrier(PIPE_ALL);
-            }
-
-            if (l2_swimlane_enabled) {
+            if (l2_swimlane_enabled) {
                 uint64_t task_token_raw = exec_payload->local_context.async_ctx.task_token.raw;
                 l2_swimlane_aicore_commit_task_record(
                     l2_swimlane_record, task_token_raw, task_id, receive_time, start_time, end_time
                 );
             }
+
+            last_reg_val = reg_val;
+            write_reg(RegId::COND, MAKE_FIN_VALUE(task_id));
🤖 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/tensormap_and_ringbuffer/aicore/aicore_executor.cpp` around
lines 235 - 250, Move the l2_swimlane_aicore_commit_task_record call in the
execution path before write_reg(RegId::COND, MAKE_FIN_VALUE(task_id)) publishes
FIN. Keep the existing profiling guard and record arguments unchanged, ensuring
the reserved L2 record is fully committed before completion becomes visible.
🤖 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.

Outside diff comments:
In `@src/a5/runtime/tensormap_and_ringbuffer/aicore/aicore_executor.cpp`:
- Around line 235-250: Move the l2_swimlane_aicore_commit_task_record call in
the execution path before write_reg(RegId::COND, MAKE_FIN_VALUE(task_id))
publishes FIN. Keep the existing profiling guard and record arguments unchanged,
ensuring the reserved L2 record is fully committed before completion becomes
visible.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 702151c7-aac7-43c8-9bef-0535e7b6d8c9

📥 Commits

Reviewing files that changed from the base of the PR and between ce81c97 and 219bb78.

📒 Files selected for processing (3)
  • src/a5/runtime/tensormap_and_ringbuffer/aicore/aicore_executor.cpp
  • tests/ut/cpp/CMakeLists.txt
  • tests/ut/cpp/common/test_l2_swimlane_aicore.cpp

@yanghaoran29
yanghaoran29 force-pushed the perf/a5-l2-reserve-commit branch from 219bb78 to 7e5276b Compare July 31, 2026 01:32
@yanghaoran29

Copy link
Copy Markdown
Contributor Author

@coderabbitai Reviewed the FIN/commit ordering against the shared AICore buffer protocol. Keeping the existing ordering intentionally: FIN does not publish the L2 buffer to the host. AICPU defers the old generation behind s_aicore_pending_enqueue and releases it only after ACK of the next generation’s first task; because AICore processes tasks serially, that ACK occurs after the prior record’s commit + dcci + dsb. This preserves record visibility while excluding DFX commit overhead from task completion timing, matching the current a2a3 lifecycle. The branch is also rebased onto current main.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@yanghaoran29 Thanks for the detailed protocol clarification. The deferred enqueue/release mechanism and serialized AICore execution establish that the prior generation’s commit + dcci + dsb completes before the next-generation ACK can release it. Keeping FIN ahead of the DFX commit is therefore intentional and consistent with the a2a3 lifecycle, while keeping commit overhead out of completion timing.

I’m withdrawing the ordering concern. 🐇


✏️ Learnings added
Learnt from: yanghaoran29
URL: https://github.com/hw-native-sys/simpler/pull/1603

Timestamp: 2026-07-31T01:33:08.009Z
Learning: In the A5 AICore shared L2-buffer protocol, FIN does not publish a completed buffer generation to the host. AICPU keeps the old generation deferred via `s_aicore_pending_enqueue` and releases it only after the ACK for the next generation’s first task. Because AICore processes tasks serially, that ACK occurs after the previous task’s L2 record `commit + dcci + dsb`, preserving host visibility. The FIN-before-DFX-commit ordering is intentional to exclude DFX commit overhead from task-completion timing and matches the a2a3 lifecycle.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

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