Skip to content

WEEKLY_CHANGES_2026 06 05_zh

ChaoZheng109 edited this page Jun 12, 2026 · 2 revisions

simpler 每周对外变更 (2026-06-05 ~ 2026-06-11)

本文通过示例对比呈现核心的接口与特性变更;细节见各 PR。

一、接口变更

本周无接口变更 —— 下面的用户可见变更均为新增、可选项,已有 example / ST 代码无需迁移。


二、新增特性

1. a5 AICore SIMT (mscatter) 启动支持 — #764

动机: 含 SIMT 向量指令(MSCATTER 等 —— SIMD 路径无法表达的逐元素 gather/scatter)的核此前在 a5 上根本无法 launch。legacy 启动路径靠读 ELF 里 bisheng emit 的 TLV 记录来分类核的向量单元使用,但 KERNEL_ENTRY 派发到独立 编译的 task .o,派发核本身暴露不出任何向量单元使用,任何 SIMT launch 都被 107000(param-invalid)拒绝。这把整整一类 element-scatter 核挡在 a5 之外。

现在 a5 AICore 路径可以 launch 含 SIMT 向量指令的 AIV 核;由新增的 simt_basic ST 验证。

// kernels/aiv/kernel_simt_scatter.cpp — 可在 a5 上 launch 的核里的 SIMT 指令
MSCATTER<Coalesce::Elem, ScatterAtomicOp::None, ScatterOOB::Skip>(
    outGlobal, srcTile, idxTile);   // out[idx[r,c]] = src[r,c]
pytest tests/st/a5/tensormap_and_ringbuffer/simt_basic --platform a5

通过一个永不执行的 VF anchor 让 bisheng 自动 emit 分类记录;同时核必须声明一个 SIMD 伴随,使其归类为 MIX(而非 SIMT-only —— 后者会反过来拒绝共享派发器上的 所有 SIMD launch)。详见 docs/simt-launch.md


2. L3 ring allreduce 示例 — #975

动机: 此前唯一的 collective 示例是 mesh 版 allreduce_distributed/。ring 拓扑是 allreduce 的另一种规范形态 —— 每个 rank 只与左右两个邻居通信、每步只搬 1/P 的数据(先 reduce-scatter 再 allgather),rank 数增大时比 mesh 更省带宽。 提供一个可运行的 L3 示例,给用户一份写"分块、逐轮信号、用 CommRemotePtr 读 邻居"的 ring collective 的参考实现。

新增 examples/workers/l3/allreduce_ring_distributed/ —— 分块 ring allreduce(逻辑环上的 reduce-scatter + allgather),区别于已有的 mesh allreduce_distributed/

python examples/workers/l3/allreduce_ring_distributed/main.py -p a2a3 -d 5-6

ring 使用 +10624B 的 HCCL window(分块 + 逐轮信号),mesh 版用 4096B。 已在 a2a3 验证。


3. device-log 时序读取 — --enable-device-log-timing#1017

动机: 设备侧的时序解析能力在 #787 被移除,此后看 on-device Total/Orch/Sched 时序的唯一途径就是 L2 swimlane JSON。但普通 benchmark、 --rounds N 多轮、以及外部 workload(如 pypto-lib 模型)从不产出 l2_swimlane_records.json,这些 run 因此完全读不到设备时序,只能看 host 侧 wall clock。本 PR 恢复 device-log 路径,让任意 profiling run 都能暴露其 orchestration / scheduler 开销。

现在普通 PTO2_PROFILING run(无需 L2 swimlane JSON)即可读到 on-device 的 每轮 Total / Orch / Sched

# 由测试框架自动打印每轮表格(单轮或多轮)
pytest tests/st/... --platform a2a3 --enable-device-log-timing --rounds 50

# 独立 CLI,可对任意 device log(含外部 workload)使用
python -m simpler_setup.tools.device_log_timing -d 0

仅 onboard L2。device-log 路径解析按 ASCEND_PROCESS_LOG_PATH > ASCEND_WORK_PATH > 有效 uid 的真实 home —— 而非 $HOME —— 因此 sudo / task-submit(以 root 跑)产生的日志也能找到。详见 docs/dfx/l2-timing.md


4. 仅 JSON 的 tensor-dump 等级(FULL_JSON_ONLY) — #1021

动机: dump 等级原本只控制"抓哪些 task",JSON 与 BIN 总是一起产出,所以哪怕 只想要每 task 的 tensor 结构,也被迫连同抓下全部 payload。大 run 下这种全量 payload 拷贝既昂贵又不安全:device→host 带宽、产生截断/覆写异常的 arena 压力、 以及磁盘上的大 .bin 文件 —— 当你只需要 shape/dtype/strides 时这些全是浪费。 等级 3 让只要结构的消费者彻底跳过 payload。

新增 dump 等级 3:把每个 task 的 tensor/scalar metadata 写入 tensor_dump/tensor_dump.json,但不抓 payload不产 .bin —— 面向只 需要每 task 结构(dtypeshapestrides、scalar value)而非元素数据的 消费者。

pytest tests/st/... --dump-tensor 3      # 0=off, 1=partial, 2=full, 3=full JSON-only
config.enable_dump_tensor = 3            # ChipWorker / CallConfig (nanobind)

等级 3 下设备不做 payload 拷贝、host 不写 .bin("bin_file": null,每条 "bin_size": 0),从而避免 full 模式的 device→host 带宽、arena 压力与磁盘开销。 dump_viewer.py 能容忍 null 的 bin_file


5. 区分 dtype 的标量 tensor dump — #966

动机: 每个被 dump 的标量,无论真实 dtype 是什么,都按 raw UINT64 位模式 写出。于是一个值为 1.5FLOAT32 标量在 dump 里显示成 4593671619917905920 —— 要看真实值得手动反解这串位。这让标量 dump 对调试 浮点(及其他有类型的)标量参数基本不可用。

现在 tensor-dump 产物里的标量值会保留其真实 dtype,并按 dtype 感知的格式导出, 不再一律按 raw UINT64 位模式输出。

# tensor_dump.json —— 一个 FLOAT32 标量参数
- { "dtype": "UINT64",  "value": 4593671619917905920 }
+ { "dtype": "FLOAT32", "value": 1.5 }

FLOAT32 解码为浮点;INT32/UINT32/BOOL/INT64 按 dtype 格式化;未知/缺失 dtype 仍回退到 raw UINT64。viewer 新增 uint16 / uint32 / bool 的呈现。


6. scope_stats —— 新增 dep_pool 资源通道 + 报告增强 — #992

动机: scope_stats 报告各 scope 的资源高水位,好让你给 ring / pool 定合适的 容量;但它此前只跟踪 task_windowheaptensormap,没有调度器的依赖 列表池(dependency-list pool)。dep_pool 耗尽是派发 back-pressure 的一个真实 来源,而报告里没有这条通道时,这种压力是看不见的。本 PR 加上 dep_pool 跟踪 (并把 HTML 报告做得更清晰),让之前测不到的这个池显现出来。

scope_stats 现在会采集并上报 dep_pool 资源通道(每 ring 的依赖列表池容量 / 占用),与已有的 task_window / heap / tensormap 并列;HTML 也改进了 top peaks、资源压力图、hover 详情、展开图视图。

config.enable_scope_stats = 1   # CallConfig —— 产出 <output_prefix>/scope_stats/scope_stats.jsonl
# 把 jsonl 转成自包含 HTML 报告(scene-test 框架也会在每个 case 后自动出图)
python simpler_setup/tools/scope_stats_plot.py <output_prefix>/scope_stats/scope_stats.jsonl

新增报告字段:dep_pool_max(按 ring)与每个边界的 dep_pool_start / dep_pool_end。详见 docs/dfx/scope-stats.md。修 #991。


7. L2 swimlane —— 队列深度 track + 依赖因果箭头 — #1000

动机: swimlane 原本能看每个调度 phase 的耗时,但有两件事看不出来:(1) 某个 任务起步晚,到底是就绪队列堵了(真正的调度压力)还是只是 MMIO / 派发延迟——光 看聚合时间区分不出来;(2) 是哪个任务完成真正解锁了哪个下游任务。本 PR 把这 两条因果线索都画成 Perfetto 的 track / 箭头。

swimlane 现在多渲染两条因果线索:

  • 队列深度 counter track —— 每个调度线程一条 local_ready_buf_T{0,1,2},外加 全局 shared_ready_queue,在每个 scheduler-phase 边界采样,于是 依赖释放 → 压 local → flush 到 shared → 对端 pop 的流转能直接读出来,而不用 从聚合时间里猜。
  • Complete↔task 箭头 —— 点一个任务即可看到 inbound complete 箭头(锚在它 最后一个 subtask 的 AICore end)和 outbound complete→ready 箭头指向它解锁的 消费者(只画"送达消费者最后一次 fanin"的那个 complete)。
# 裸 flag = level 4(full);队列深度 + complete 连线需要 scheduler-phase 记录,
# 即 --enable-l2-swimlane level >= 3(SCHED_PHASES)
pytest tests/st/... --platform a2a3 --enable-l2-swimlane

生成的 trace 在 Perfetto UI 里打开。outbound complete→ready 箭头需要 deps.json(静态 DAG);没有它就只画 inbound 箭头。热路径开销通过 lazy 采样 shared 队列控制在 <1%


三、用户可见的缺陷修复

PR 修复说明
#1030 层级/组合派发在调用一个含大量张量参数的 child kernel(如 76 tensors + 2 scalars)时,即便每个描述符都合法,也会被 WorkerThread::dispatch_process: args blob exceeds mailbox capacity 拒绝 —— worker mailbox 容量过小(4096 → 16384 字节)。