Skip to content

[Code Health] Reconcile a2a3 vs a5 tensormap_and_ringbuffer runtime implementation divergence #1582

Description

@ChaoZheng109

Category

Technical Debt (cleanup, refactor)

Component

AICPU Scheduler

Description

tensormap_and_ringbuffer (tmr) 运行时有两份实现:src/a2a3/runtime/tensormap_and_ringbuffer/src/a5/runtime/tensormap_and_ringbuffer/。目标是两份尽量保持一致,仅在硬件/架构确有要求处才允许差异。

对 tmr 全树做内容级 diff(基线 upstream/main @ ca22a8f4)后的结论:文件结构相同(a5 仅多 urma 后端),差异全在实现内容。strace / timing / L2-swimlane / profiling 计装已代码级对齐strace_timingswimlane_converter.py 在 a5 可用),无需处理。

说明:下表行号用 A1..A9,避免与 GitHub 的 PR/issue 自动链接混淆。文中形如 #1328 的四位号才是真实 PR 引用。

方向判定方法(重要)

两棵树共享 git 历史:仓库初始大导入 commit 8b34712b(#1100) 一次性建立了 a2a3 与 a5 两棵树,且导入那一刻两树部分内容就已不同(同一 commit 里 a2a3/a5 版本各异)。此后多数 PR 用 (a2a3 + a5) 标题同时改两树,分叉只来自少数单边 PR。因此 git blame 会把所有行归到 #1100不能用来判断方向。方向只能由“导入后单边 PR 到底改了哪棵树”来确定:

主表:a5 落后 a2a3(有单边 PR 证据,需从 a2a3 移植)

领域 a5 现状 vs a2a3 能力 影响 方向证据(a2a3 单边 PR,a5 改动=0)
A1 dispatch 热路径 a5 每次派发都 AsyncCtx::make+清 slab;a2a3 在 init() 按 (core,buf) 预填、每派发只写 task_token 性能(每任务,最大) #1328 perf(a2a3/tmr): shrink dispatch cold-write cost#1345
A2 调度结构 a5 无正常 sync_start 车道,全走 stop-the-world drain;a2a3 有 ready_sync_queues[] Tier-0 + run_staging_order 性能+结构(最大结构差) #1319(a2a3=4/a5=0);#1285/#1292/#1405
A3 调度并发 a5 dummy 队列固定 thread 0(batch 16);a2a3 跨 sched 线程并行 thread_idx<3(batch 8) 性能(a5 未用多余 sched 线程做 dep-only resolve;a5 串行是安全的,非竞态 bug) 已证#1263 同改两树,把 a2a3 从 thread0 改为 thread_idx<3 并行化,a5 有意保留 thread0 并加注“避免跨线程竞争”。a5 落后,但补齐需先具备并行安全前提(MPMC + per-slot 原子)
A5 AICore executor a5 旧合并型 L2 记录、DFX 关也每次读计时器、记录可能跨缓冲代;a2a3 reserve/commit 拆分+计时门控 正确性+性能 #1513(a2a3=1/a5=0)
A6 dispatch 微优化 a5 无 prefetch_block_dst;a2a3 有 性能(低风险) #1328(a2a3 单边,a5 无此符号)
A7 DFX 计数 a5 缺 phase_subretire_count(a2a3 的 SPMD 子块-retire 计数) 可观测性(须与 swimlane_converter.py 同 PR,见 #1382 已证:a2a3 #1288 单边引入,a5 从未有
A8 host 接口 a5 无 get_pipeline_contract()Tier-C extern-C ABI,跨仓消费) 能力缺失(需协调移植) #1463(a2a3=1/a5=0)
A9 AICPU 健壮性 a5 无 run() thread-idx 边界检查 健壮性(轻微) #1119(a2a3=3/a5=0)

A4 已撤销(2026-07-29 核实):原判“a5 缺 gated MIX per-core split”为误报。去注释精确比对后,正常 MIX per-core placement(idle 核→running、busy 核→pending,即 #1308)、classify_mix_cluster 定义、drain 路径 mix_split 三处代码两树完全一致。原以为的差异实属 A2 的队列参数化(a2a3 disp_queues[] vs a5 硬编码 ready_queues)。唯一遗留:a5 scheduler_dispatch.cpp 一条注释自相矛盾(写“not a2a3 gated MIX split”但代码正是该 placement),可顺手修正。

导入即分叉:方向无 git 依据(原先误判为“a2a3 落后 a5”,已更正)

这些差异自 #1100 导入即存在、此后两树都无单边改动,-S 追踪只有 #1100 一条。不能断言谁落后——只是仓库诞生时两份代码就不同。需要的是人工决定以哪种写法为准并统一到两树(rule 10:一次提交、全部树),而不是当作 a5 领先来追。

a2a3 现状 a5 现状 需人工决定
PTO2_SCOPE_GUARD 无参 () 可变参 (...) 以哪种为准
payload 预取 成员 payload->prefetch() 自由函数 prefetch_payload() 以哪种为准
TaskSubmitResult alias 存在(零使用) 大概率两树都删
pto2_submitted_tasks/read_pto2_runtime_status 保留 PTO2 前缀 已去前缀 按 rule 9/10 统一去前缀
sched_scan_cycle 计数 无(全历史从未有) 有(#1100 导入即有) a5 独有、a2a3 从无——决定去留(非 a2a3 落后
init_from_layout 残留 3 处 2 处 基本一致,仅清理残留

补充:a5 注释 sizeof(PTO2TaskSlotState) 写"32 bytes"但 static_assert 为 64 —— 这是 a5 注释 bug,直接修 a5。

文档修正(代码已对,无需改码)

文档 问题
src/a5/.../docs/profiling_levels.md 描述旧 complete_task 结合型 level-1,与 a5 自身 decoupled 代码矛盾
src/a5/.../docs/MULTI_RING.md 写了不存在的 API pto2_make_task_id()(两树实际都用 PTO2TaskId::make

必要差异(arch 决定,不要同步)

原因 关联
AICore PMU per-task ring(pmu_aicore_record_task)a5 独有 a5 领先;a2a3 硬件能力不足,不 back-port
a5 删除 cache invalidate/flush(deinit / async-wait counter-line / SDMA record / PMU record) a5 AICPU 与 DMA/HBM 缓存一致,顺序由 acquire/release 原子保证;a3 需要而 a5 不需要 #1235 (153daee6)
core_num / s_block_idx / s_block_num a5 编译器要求block_idx/block_num 为内建保留符),不能回退;如需统一只能 a2a3 采用 a5
urma 后端 + backend_cookie a5 硬件专有 #1392
核数/频率常量、DMB MMIO 偏移 0xD0、头文件 guard SRC_A5_* dav-c310 硬件

待验证reserve_layouttask_window_sizes[] 重载方向("a5 缺失" vs "a5 删了 dead 参数")——动手前先确认。

Location

基线 upstream/main @ ca22a8f4。两树对照:

  • src/a2a3/runtime/tensormap_and_ringbuffer/
  • src/a5/runtime/tensormap_and_ringbuffer/

按主表定位:A1 runtime/scheduler/scheduler_dispatch.cpp,scheduler_cold_path.cpp;A2 runtime/scheduler/pto_scheduler.h,scheduler_dispatch.cpp,runtime/shared/pto_runtime2_init.cpp;A3/A4/A6 scheduler_dispatch.cpp;A5 aicore/aicore_executor.cpp;A7 runtime/scheduler/* + simpler_setup/.../swimlane_converter.py;A8 host/runtime_maker.cpp;A9 aicpu/aicpu_executor.cpp

Proposed Fix

拆成多个小 PR 分批落地(禁止一个大 diff)。推荐补齐顺序:

阶段 包含项 目标 前置 / 风险
P0 热路径性能 A1, A5, A6(方向已证) 补齐每任务开销最大的 AICPU/AICore dispatch 优化 A5 需与 a5 的 PMU-ring/lazy-head 协调;保留 a5 backend_cookie/s_block 命名
P1 调度结构决策 A2, A3 补齐 sync_start 车道与 dummy-drain 并发 需 sync_start/dep-pool owner 签字(移植 a2a3 双车道 vs 采纳 a5 单车道);A3 是竞态需先确认
P2 DFX 对齐 A7 swimlane 计数对齐(phase_subretire_count 必须与 swimlane_converter.py+文档同 PR(#1382
P3 外部 ABI A8 get_pipeline_contract() Tier-C ABI,需跨仓协调,勿盲拷
P4 命名/写法统一 “导入即分叉”表全部 消除生而不同的差异 先人工决定每项以哪种写法为准(非“a2a3 追 a5”);rule 10 一次提交全部树
P5 文档 profiling_levels.md, MULTI_RING.md 修文档 无依赖,可随时做

关联:#1548, #545

Priority

Medium (minor risk, should fix in next few releases)

Metadata

Metadata

Assignees

Labels

code healthTechnical debt, robustness, code quality

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions