Skip to content

Add: select A5 AICPU cores from runtime topology - #1643

Open
yanghaoran29 wants to merge 1 commit into
hw-native-sys:mainfrom
yanghaoran29:add/a5-fg-pg-core-selection
Open

Add: select A5 AICPU cores from runtime topology#1643
yanghaoran29 wants to merge 1 commit into
hw-native-sys:mainfrom
yanghaoran29:add/a5-fg-pg-core-selection

Conversation

@yanghaoran29

@yanghaoran29 yanghaoran29 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Scope

This change adds topology-aware AICPU core selection for A5.

The runtime combines the authoritative device-side AICPU scheduler pool with Host CPU_TOPO metadata, classifies known FG, PG1, and PG2 topologies, and applies scenario placement for every supported active thread count from 2 through 5. Scheduler SMT availability is recorded as an independent topology property; it does not define a separate FG scenario.

A5 now supports at most five active AICPU threads. The independent launch population remains capped at 14 so the affinity gate can cover the device-visible scheduler pool.

Changes

  • Query device-side OCCUPY, PF_OCCUPY, and OS_SCHED before normal AICPU work.
  • Prefer driver CPU_TOPO metadata and lock Host/AICPU wire layouts with compile-time ABI assertions.
  • Match packaged fallback entries by SoC and every constraint declared by that entry. Ascend950PR_9599 requires exact OCCUPY 0x1f8 on either Host architecture; Ascend950PR_9579 also constrains Host architecture.
  • Apply parameterized FG, PG1, and PG2 placement to manual and automatic active counts from 2 through 5.
  • For UNKNOWN topology, use topology order when metadata is valid and CPU-ID order for OCCUPY-only metadata. Manual counts must be satisfied exactly; automatic mode may shrink from five but keeps at least one Scheduler and one Orchestrator.
  • Keep explicitly generic verified fallbacks on the generic topology-aware packer.
  • Cache successful merged topology probes for one DeviceRunner lifetime and invalidate them on recovery, reset, and finalize.
  • Keep Runtime, DFX, affinity, and actual launch-count state consistent.
  • Extend aicpu-device-query with A5 classification and diagnostic JSON output.
  • Update design, hardware, runtime, and DFX documentation to the five-thread cap.

Verification

  • Final code review: passed with no remaining findings.
  • pre-commit run --from-ref upstream/main --to-ref HEAD: passed.
  • C++ unit tests: 80/80 passed; A5 topology/selection target contains 23 tests.
  • A5 onboard Host/AICPU/AICore builds passed for both host_build_graph and tensormap_and_ringbuffer.
  • aicpu-device-query Host build passed.

@coderabbitai

coderabbitai Bot commented Aug 3, 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: a2733837-c669-484c-a4b2-dc21390ce193

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 PR adds a production AICPU topology query, occupancy-aware host probing, scenario-specific CPU selection, unknown-topology fallback, runtime thread-count adjustment, and diagnostic JSON output for A5.

Changes

A5 AICPU topology flow

Layer / File(s) Summary
Topology query contract and entry point
src/a5/platform/include/common/kernel_args.h, src/a5/platform/onboard/aicpu/*, src/common/aicpu_loader/*, src/a5/runtime/*
Adds the topology query payload, HAL-backed simpler_aicpu_query_topology entry point, build linkage, and runtime symbol exports.
Topology classification and CPU selection
src/a5/platform/onboard/host/aicpu_topology_probe.*, tests/ut/cpp/a5/test_aicpu_topology_fallback.cpp
Adds occupancy-aware probing, FG/PG classification, known-scenario affinity policies, unknown-topology fallback selection, JSON serialization, and unit tests.
Runtime occupancy and launch integration
src/a5/platform/onboard/host/device_runner.*, src/a5/docs/hardware.md
Queries and caches device occupancy, applies topology selection, adjusts effective runtime thread counts, preserves the full launch population, and resets cached state.
Diagnostic JSON flow and documentation
tools/cann-examples/aicpu-device-query/*, docs/design/a5-fg-pg-core-selection.en.md
Adds --json topology output, required build and link settings, and documentation for production querying and fallback behavior.

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

Sequence Diagram(s)

sequenceDiagram
  participant DeviceRunner
  participant AICPUQuery
  participant AscendHAL
  participant TopologyProbe
  participant AICPUThreads
  DeviceRunner->>AICPUQuery: query device occupancy
  AICPUQuery->>AscendHAL: request occupancy metrics
  AscendHAL-->>AICPUQuery: return topology values
  AICPUQuery-->>DeviceRunner: return occupancy result
  DeviceRunner->>TopologyProbe: classify topology and select CPUs
  TopologyProbe-->>DeviceRunner: return affinity and effective count
  DeviceRunner->>AICPUThreads: launch full OCCUPY population
Loading

Possibly related PRs

Poem

A rabbit queries cores in a row,
Through HAL paths where occupancy values flow.
Five CPUs hop into place,
With O at the end of the race.
JSON rests clean, warnings stay low.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.14% 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: selecting A5 AICPU cores from runtime topology.
Description check ✅ Passed The description directly explains topology-aware A5 AICPU selection, classification, fallback behavior, diagnostics, and verification.

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.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/a5/platform/onboard/host/aicpu_topology_probe.cpp (2)

483-485: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Return a value tuple from topology_key.

std::tie returns std::tuple<const int32_t&, ...> bound to the members of cpu. All current callers compare the result inside the same full expression, so the references stay valid. The signature is still fragile. A future caller that stores the result, or that passes a temporary AicpuLogicalCpu, gets dangling references with no compiler diagnostic. The members are five int32_t, so a value tuple costs nothing.

♻️ Proposed change to return a value tuple
 auto topology_key(const AicpuLogicalCpu &cpu) {
-    return std::tie(cpu.die_id, cpu.cluster_id, cpu.phy_cpu_id, cpu.hyperthread_id, cpu.cpu_id);
+    return std::make_tuple(cpu.die_id, cpu.cluster_id, cpu.phy_cpu_id, cpu.hyperthread_id, cpu.cpu_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/platform/onboard/host/aicpu_topology_probe.cpp` around lines 483 -
485, Update topology_key to return a value tuple containing the five int32_t
topology fields instead of using std::tie, ensuring results remain valid when
stored or when the input is temporary.

676-694: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Escape soc_name before you write it into the JSON string.

Line 683 interpolates topology.soc_name directly between quotes. The value comes from aclrtGetSocName() through query_soc_name(), so this code does not control its content. A " or \ in that value produces malformed JSON for every consumer of --json output. Observed SoC names are alphanumeric, so this is a robustness gap and not a current failure.

A related point on line 679-681: the ternary chain uses "sequential_fallback" as the catch-all. If a fourth AicpuSelectionPolicy enumerator is added, the output silently reports the wrong policy. A switch gives you a compiler warning instead.

♻️ Proposed fix for escaping and the policy mapping
+std::string json_escape(const std::string &value) {
+    std::string out;
+    out.reserve(value.size());
+    for (char c : value) {
+        if (c == '"' || c == '\\') {
+            out += '\\';
+            out += c;
+        } else if (static_cast<unsigned char>(c) < 0x20) {
+            char buf[7];
+            std::snprintf(buf, sizeof(buf), "\\u%04x", static_cast<unsigned char>(c));
+            out += buf;
+        } else {
+            out += c;
+        }
+    }
+    return out;
+}
+
 std::string format_aicpu_topology_json(
     const AicpuTopology &topology, AicpuSelectionPolicy policy, const std::vector<int32_t> &allowed_cpus
 ) {
-    const char *policy_name = policy == AicpuSelectionPolicy::kScenario ? "scenario" :
-                              policy == AicpuSelectionPolicy::kGeneric  ? "generic" :
-                                                                          "sequential_fallback";
+    const char *policy_name = "sequential_fallback";
+    switch (policy) {
+    case AicpuSelectionPolicy::kScenario:
+        policy_name = "scenario";
+        break;
+    case AicpuSelectionPolicy::kGeneric:
+        policy_name = "generic";
+        break;
+    case AicpuSelectionPolicy::kSequentialFallback:
+        policy_name = "sequential_fallback";
+        break;
+    }
     std::ostringstream out;
-    out << "{\n  \"architecture\": \"a5\",\n  \"soc_name\": \"" << topology.soc_name << "\",\n  \"scenario_type\": \""
+    out << "{\n  \"architecture\": \"a5\",\n  \"soc_name\": \"" << json_escape(topology.soc_name)
+        << "\",\n  \"scenario_type\": \""
🤖 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/platform/onboard/host/aicpu_topology_probe.cpp` around lines 676 -
694, Update format_aicpu_topology_json to JSON-escape topology.soc_name before
inserting it into the quoted "soc_name" field, including quotes, backslashes,
and other required control characters. Replace the policy_name ternary in
format_aicpu_topology_json with an exhaustive switch over AicpuSelectionPolicy
so newly added enumerators are diagnosed rather than silently mapped to
sequential_fallback.
tools/cann-examples/aicpu-device-query/host/CMakeLists.txt (1)

44-48: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Make the driver library directory overridable.

Line 47 hardcodes /usr/local/Ascend/driver/lib64/driver while every other search path in this file derives from ${ASCEND_HOME_PATH}. On a host with a non-default driver install, the ascend_hal link on line 52 fails and the tool cannot be built. A cache variable keeps the default and lets the builder override it.

♻️ Proposed change
+set(ASCEND_DRIVER_LIB_DIR "/usr/local/Ascend/driver/lib64/driver"
+    CACHE PATH "Directory containing libascend_hal.so")
+
 target_link_directories(query_device_hal PRIVATE
     ${ASCEND_HOME_PATH}/lib64
     ${ASCEND_HOME_PATH}/runtime/lib64
-    /usr/local/Ascend/driver/lib64/driver
+    ${ASCEND_DRIVER_LIB_DIR}
 )
🤖 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 `@tools/cann-examples/aicpu-device-query/host/CMakeLists.txt` around lines 44 -
48, Update the target_link_directories configuration for query_device_hal to
replace the hardcoded driver path with a CMake cache variable that defaults to
/usr/local/Ascend/driver/lib64/driver, allowing builders to override the driver
library directory while preserving the current default.
src/a5/platform/onboard/host/device_runner.cpp (1)

282-289: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Name the 5 that selects the 4S+1O policy.

The literal couples this dispatch to compute_scenario_allowed_cpus, which always returns exactly five CPUs in [S0, S1, S2, S3, O] order. The relationship is not visible at the call site. A named constant documents why any other requested count falls through to the generic compute_allowed_cpus path.

♻️ Proposed change
+// compute_scenario_allowed_cpus implements the fixed 4-scheduler + 1-orchestrator
+// policy, so it applies only when the caller requests exactly that many threads.
+constexpr int kScenarioPolicyThreadCount = 5;
-        } else if (requested_aicpu_num == 5) {
+        } else if (requested_aicpu_num == kScenarioPolicyThreadCount) {
🤖 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/platform/onboard/host/device_runner.cpp` around lines 282 - 289,
Replace the literal requested_aicpu_num == 5 check in the device runner dispatch
with a named constant representing the 4S+1O policy CPU count, defined in the
appropriate nearby scope. Use that constant when selecting
compute_scenario_allowed_cpus so the fixed five-CPU relationship is explicit
while leaving the generic fallback unchanged.
🤖 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/platform/onboard/host/device_runner.cpp`:
- Around line 162-172: Update the preflight AICPU launch and synchronization
failure branches in the device occupancy query to call
recover_device_or_mark_unusable(rc) before returning. Apply this to both
launch_aicpu_payload and aclrtSynchronizeStreamWithTimeout failures, preserving
the existing error logging and return behavior.

In `@tools/cann-examples/aicpu-device-query/host/query_device_hal.cpp`:
- Around line 498-505: Replace the magic indices used in the JSON occupancy
mapping within the query-device flow with named constants representing the
OS_SCHED, OCCUPY, and PF_OCCUPY request positions. Use those constants
consistently for both value and validity assignments, and define them alongside
the requests list so changes to request ordering remain explicit and
synchronized.

---

Nitpick comments:
In `@src/a5/platform/onboard/host/aicpu_topology_probe.cpp`:
- Around line 483-485: Update topology_key to return a value tuple containing
the five int32_t topology fields instead of using std::tie, ensuring results
remain valid when stored or when the input is temporary.
- Around line 676-694: Update format_aicpu_topology_json to JSON-escape
topology.soc_name before inserting it into the quoted "soc_name" field,
including quotes, backslashes, and other required control characters. Replace
the policy_name ternary in format_aicpu_topology_json with an exhaustive switch
over AicpuSelectionPolicy so newly added enumerators are diagnosed rather than
silently mapped to sequential_fallback.

In `@src/a5/platform/onboard/host/device_runner.cpp`:
- Around line 282-289: Replace the literal requested_aicpu_num == 5 check in the
device runner dispatch with a named constant representing the 4S+1O policy CPU
count, defined in the appropriate nearby scope. Use that constant when selecting
compute_scenario_allowed_cpus so the fixed five-CPU relationship is explicit
while leaving the generic fallback unchanged.

In `@tools/cann-examples/aicpu-device-query/host/CMakeLists.txt`:
- Around line 44-48: Update the target_link_directories configuration for
query_device_hal to replace the hardcoded driver path with a CMake cache
variable that defaults to /usr/local/Ascend/driver/lib64/driver, allowing
builders to override the driver library directory while preserving the current
default.
🪄 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: 82f4f0d8-f319-482a-9e81-bffd2ebdee27

📥 Commits

Reviewing files that changed from the base of the PR and between 04e0733 and 388d7ad.

📒 Files selected for processing (16)
  • docs/design/a5-fg-pg-core-selection.en.md
  • src/a5/docs/hardware.md
  • src/a5/platform/include/common/kernel_args.h
  • src/a5/platform/onboard/aicpu/CMakeLists.txt
  • src/a5/platform/onboard/aicpu/kernel.cpp
  • src/a5/platform/onboard/host/aicpu_topology_probe.cpp
  • src/a5/platform/onboard/host/aicpu_topology_probe.h
  • src/a5/platform/onboard/host/device_runner.cpp
  • src/a5/platform/onboard/host/device_runner.h
  • src/a5/runtime/host_build_graph/host/runtime_maker.cpp
  • src/a5/runtime/tensormap_and_ringbuffer/host/runtime_maker.cpp
  • src/common/aicpu_loader/host/load_aicpu_op.h
  • tests/ut/cpp/a5/test_aicpu_topology_fallback.cpp
  • tools/cann-examples/aicpu-device-query/README.md
  • tools/cann-examples/aicpu-device-query/host/CMakeLists.txt
  • tools/cann-examples/aicpu-device-query/host/query_device_hal.cpp

Comment thread src/a5/platform/onboard/host/device_runner.cpp Outdated
Comment thread tools/cann-examples/aicpu-device-query/host/query_device_hal.cpp Outdated
@yanghaoran29
yanghaoran29 force-pushed the add/a5-fg-pg-core-selection branch 9 times, most recently from 2b60f55 to b704cbd Compare August 3, 2026 11:35
@yanghaoran29 yanghaoran29 changed the title Add: implement A5 FG/PG AICPU core selection Add: select A5 AICPU cores on verified 9599 and 9579 devices Aug 3, 2026
@yanghaoran29
yanghaoran29 force-pushed the add/a5-fg-pg-core-selection branch from b704cbd to dcbf182 Compare August 3, 2026 13:13
@yanghaoran29

Copy link
Copy Markdown
Contributor Author

@coderabbitai Addressed the remaining review suggestions:

  • topology_key now returns a value tuple.
  • topology JSON escapes the SoC name and maps selection policies with an exhaustive switch.
  • the fixed 4S+1O thread count has a named constant.
  • the driver library directory is an overridable CMake cache path.
  • JSON fallback helpers are grouped at the end of aicpu_topology_probe.cpp.

Validation passed: the 16 A5 topology unit tests, pre-commit, and a separate clang-tidy run.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Your plan includes PR reviews subject to rate limits. Reviews are available now.

@yanghaoran29
yanghaoran29 force-pushed the add/a5-fg-pg-core-selection branch 3 times, most recently from 497c7f9 to c83b46b Compare August 4, 2026 02:14
@yanghaoran29 yanghaoran29 changed the title Add: select A5 AICPU cores on verified 9599 and 9579 devices Add: select A5 AICPU cores from runtime topology Aug 4, 2026
@yanghaoran29
yanghaoran29 force-pushed the add/a5-fg-pg-core-selection branch 6 times, most recently from fbcc1d6 to 49872b1 Compare August 5, 2026 09:27
@yanghaoran29

Copy link
Copy Markdown
Contributor Author

Clarification on the A5 AICPU launch count and the constant 14:

  • Onboard first launches a separate one-thread preflight kernel to read the device-side AICPU OCCUPY mask.
  • The main-kernel launch count is the number of stable reachable CPU IDs after merging CPU_TOPO with that OCCUPY mask. If live CPU_TOPO is unavailable, the packaged JSON fallback is tried before the generic OCCUPY-only fallback. In the normal case, the resulting launch count is popcount(OCCUPY).
  • PLATFORM_MAX_AICPU_THREADS_JUST_FOR_LAUNCH=14 is a compile-time capacity bound, not the default or an unconditional launch count. It also sizes the per-launched-thread phase and task-timing storage.
  • For example, six stable reachable CPUs cause a six-thread main launch; the default policy keeps five active roles (4 Scheduler + 1 Orchestrator) and drops one. Fourteen stable reachable CPUs cause a fourteen-thread main launch and retain five active roles. More than fourteen is rejected instead of clamped.
  • A5 simulation is different: it deliberately creates fourteen simulated AICPU threads and applies the gate afterward because there is no real device OCCUPY query.
  • The value 14 corresponds to the expected widest 0x7ffe occupancy (7 physical CPUs x 2 SMT threads). Whether that SKU can complete a real fourteen-thread production launch still requires hardware validation; the code does not silently reduce a failed fourteen-thread launch.
  • Automatic active count defaults to five and may shrink when fewer CPUs are stably reachable; explicit active counts are exact in the supported 2-5 range. The runtime warns both when stable reachable capacity is below five and when live CPU_TOPO is unavailable.

Build one launch plan for active roles, full reachable launch coverage, warnings, and FG/PG affinity.

Default PG1 to minimum SMT sharing, consolidate topology constants, and document verified live FG topology.

Cover the documented Compute-only layouts with deterministic topology unit tests.
@yanghaoran29
yanghaoran29 force-pushed the add/a5-fg-pg-core-selection branch from 49872b1 to bfbcc5f Compare August 5, 2026 10:47
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