CANNBot Step 1→7 在 MC2 场景下的工作流映射
【免费下载链接】cannbot-skillsCANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体,本仓库为其提供可复用的 Skills 模块。项目地址: https://gitcode.com/cann/cannbot-skills
本文档把父级plugins-official/ops-direct-invoke/AGENTS.md的 7 步流程具体化到 MC2 通算融合算子场景。CANNBot 主控和 Architect/Developer/Reviewer 三类 Subagent 在每个 Step 进入前都应先读对应小节,明确"本阶段在 MC2 场景下要做什么、门禁是什么、调用哪些 skill"。
父级流程定义以
plugins-official/ops-direct-invoke/AGENTS.md为准;本文件只补充 MC2 场景的差异化要点,不重写父级规则。
Step 1:环境检查(门禁)
标准动作(父级定义)
按ascendc-env-checkskill 运行:
npu-smi info查设备列表与状态;- 检查
ASCEND_HOME_PATH/CANN_TOOLKIT_HOME等环境变量; - 运行
workflows/scripts/verify_environment.sh {operator_name},生成environment.json。
MC2 场景额外校验
| 校验项 | 命令 / 方法 | 失败处理 |
|---|---|---|
| NPU 架构必须为 dav-3510 | npu-smi info读Chip Name应为Ascend 950系列;CMake 阶段再次校验NPU_ARCH=dav-3510 | 非 3510 直接终止,告知用户"本 skill 仅支持 Ascend 950 (dav-3510)" |
| SHMEM 第三方库可解析 | 检查references/all_to_all_matmul/third_party/shmem/symlink 是否指向有效路径;若不存在,cmake/shmem.cmake会触发git submodule update --init | 提示用户初始化 submodule |
| tensor_api(Blaze 头)可解析 | 同上,检查third_party/tensor_api/ | 提示用户初始化 submodule |
| 多卡环境可用 | npu-smi info至少能看到rankNum张卡(默认 4 卡) | 提示用户准备多卡环境;单卡只能跑精度模式,性能模式需多卡 |
门禁
environment.json的validation.all_passed=true且上述 MC2 校验全部通过 → 进入 Step 2。任何一项失败禁止进入 Step 2,告知用户原因。
Step 2:设计(Architect)
输出物
父级要求双文件:operators/{op}/docs/DESIGN.md+operators/{op}/docs/PLAN.md。MC2 场景下 DESIGN.md必须额外包含以下小节(Reviewer 在 Step 4 会交叉检查):
§三大约束显式确认
## 三大约束确认 ### 约束 1:通信走 SHMEM - 选用的 SHMEM 原语:<aclshmemx_udma_put_nbi / aclshmemx_barrier_all_vec / ...> - 确认无 Hccl:: 高阶 API:✅ ### 约束 2:Matmul 走 Blaze - 选用的 Blaze 模板:<Blaze::Gemm::Block::BlockMmad + Kernel::QuantMatmulMxKernelSwat 等> - DispatchPolicy:<MatmulWithScaleMx / ...> - 确认无 asc-devkit matmul API:✅ ### 约束 3:流程合规 - 复用基底:references/all_to_all_matmul/ - 计划修改的文件清单:<列出 [MODIFY] 文件>§切分策略
- 两阶段
tileCnt策略(详见pipeline_tuning.md):- Step 2-4 设计/审查阶段:
tileCnt=1(headMSize=m)做串行基线,简化精度/审查调试; - Step 6 性能验收阶段:扫描
tileCnt ∈ {1, 2, 4, 8, 16, 32}找最优,headMSize=512只是起点不是最优值。
- Step 2-4 设计/审查阶段:
- M 轴切分:
headMSize = m / tileCnt,bufferSize=4 - SHMEM 空间预算(默认 1 GB,需够装下
rankSize * bufferSize * bufferBlockSize + scale)
§AIV/AIC 分工图
明确哪些 work 在 AIV(通信),哪些在 AIC(计算),同步点在哪里(CrossCoreSetFlag<0x2, PIPE_*>)。
Architect 加载顺序
- 加载本 skill(
ascendc-mc2-best-practice),读references/mc2_architecture.md建立整体心智模型; - 若通信侧不确定用哪个 SHMEM 原语 → 读
references/comm_shmem.md; - 若计算侧不确定用哪个 Blaze 模板 → 读
references/matmul_blaze.md; - 输出 DESIGN.md + PLAN.md。
门禁
- 双文件齐全;
- DESIGN.md 包含"三大约束确认"小节,且勾选 ✅;
- 切分策略中
headMSize等参数有可解释的依据(不能拍脑袋)。
Step 2.5:设计串讲
Developer 串讲模式关注点
- 复用的基底文件清单是否合理(不能把
[REUSE]文件错标成[MODIFY]); - AIC 是否在通信 buffer 上遍历所有 rank,rank==rankId 是否切换到本卡 GM;
- SHMEM 空间预算是否够(
rankSize * commMSize_ * kPerRank * bufferSize+ scale 段)。
Architect 串讲回应关注点
- 若 Developer 提出"想用 HCCL 替代 SHMEM" → 直接拒绝,引用 SKILL.md 约束 1;
- 若 Developer 提出"想用 asc-devkit matmul API" → 直接拒绝,引用 SKILL.md 约束 2。
收敛
严格 1 轮串讲;分歧写入 WALKTHROUGH.md## 设计串讲仲裁。
Step 3:开发(Developer)
起手流程
# 1. 从基底工程复制 cp -r references/all_to_all_matmul operators/{op_name} # 2. 按 [MODIFY] 标记定点改造 # - src/{op_name}.cpp:函数名、kernel 调用、参数解析 # - include/kernel/all_to_all_comm_udma.h:通信原语(若非 AllToAll) # - include/kernel/all_to_all_matmul_impl.h:通算融合主类 # - include/kernel/qbmm_mx_kernel.h:Blaze Kernel 包装(改 Scale/dtype/bias 时动) # - include/tiling/*:TilingData 字段 # - scripts/gen_data.py + verify_result.py:dtype/容差 # 3. 编译 cd operators/{op_name} cmake -S . -B build -DNPU_ARCH=dav-3510 cmake --build build -j # 4. 跑精度 bash run.sh # 默认 m=2048 k=8192 n=3584 rank=4 precision开发阶段红线
- 禁止新增
Hccl::调用(Reviewer 会在 Step 4 grep); - 禁止包含 asc-devkit 的 matmul 头;
- 禁止为了赶进度跳过
run.sh的精度模式直接跑 perf; - 改完每个
[MODIFY]文件后立即跑一次bash run.sh做冒烟,避免最后一次性 debug。
门禁
- 编译通过;
bash run.sh(precision 模式)输出verify_result.py: PASS;- 代码已提交到
operators/{op_name}/。
Step 4:审查(Reviewer)
必查清单(来自 SKILL.md "约束清单")
按 R1~R7 逐项检查:
# R1 架构=3510 grep -r "npu-arch" operators/{op}/CMakeLists.txt # R2 无 HCCL 高阶 API(应为空) grep -rn "Hccl::" operators/{op}/ # R3 无 asc-devkit matmul API(应为空) grep -rn "AscendC::Matmul\b" operators/{op}/ # R4 通信走 SHMEM grep -rn "shmem.h\|aclshmem" operators/{op}/include/kernel/ # R5 Matmul 走 Blaze grep -rn "blaze/gemm/block/" operators/{op}/include/ # R6 流程门禁 ls operators/{op}/docs/{DESIGN,PLAN,WALKTHROUGH,REVIEW}.md cat operators/{op}/environment.json | grep all_passed # R7 性能采集合规(在 Step 6 才完整执行;Step 4 检查 heavy_kernels.h 是否被正确 include) grep -rn "heavy_add_kernel\|cache_flush" operators/{op}/src/常见 FAIL 原因
| 现象 | 根因 | 修复方向 |
|---|---|---|
grep 到Hccl::AllReduce | 开发者把 HCCL 当成"熟悉的 API"用了 | 回退到 Step 3,要求 Developer 改写为aclshmemx_udma_put_nbi+ 自实现 Reduce 逻辑 |
grep 到AscendC::Matmul | 开发者误用 asc-devkit 接口 | 回退到 Step 3,替换为Blaze::Gemm::Block::BlockMmad |
| SHMEM 空间不足崩溃 | DESIGN.md 的空间预算没算对 | 回退到 Step 2,重算SHMEM_SPACE_SIZE |
| 精度对不上但无报错 | 多半是 ProcessSingleBatch 中 rank==rankId 分支错(未切换到本卡 GM) /remoteRankCnt没从 0 起算 | 回退到 Step 3,对照qbmm_mx_kernel.h注释核对 |
门禁
- REVIEW.md 判定
PASS或PASS WITH NOTES→ 进入 Step 6; - REVIEW.md 判定
FAIL→ 进入 Step 5 修复循环。
Step 5:修复循环
最多 3 轮。每轮:Developer 修复 → Reviewer 复审。MC2 场景下常见的"修不动"问题:
- 跨核同步 flag 错位:
CrossCoreSetFlag<0x2, PIPE_MTE3>(mLoopIdx)与CrossCoreWaitFlag<0x2, PIPE_MTE2>(mLoopIdx)的 idx 必须一致; - UDMA Put 顺序错:
aclshmemx_udma_quiet(remoteRank)必须在每次 Put 后调用,否则数据未真正下发; - remoteRankCnt 错位:
splitKNum必须等于rankSize,否则 fixpipe 时机不对(最后一次 mmadOp_ 才触发);
3 轮仍未通过 → 暂停上报用户。
Step 6:性能验收(Developer)
MC2 专用流程(必须刷 L2 cache)
详细步骤见
profiling_mc2.md。这里只给摘要。
PROJ="$(pwd)" # 1. 算子二进制已具备 perf 模式(run.sh 第 5 参传 perf) bash run.sh 2048 8192 3584 4 perf # 2. msprof task-based 采集(无 warm-up;L2 flush 由 perf 主循环内部保证) msprof --ai-core=on --aic-mode=task-based \ --output="${PROJ}/docs/perf/round_001" \ --application="${PROJ}/build/{op_name} 2048 8192 3584 4 perf" # 3. 多卡后处理:每卡取最后 5 次 main kernel 平均,4 卡取最大 python3 scripts/extract_perf.py "${PROJ}/docs/perf/round_001" AllToAllQuantMatmulKernelE4M3E4M3 5关键点
- 两阶段
tileCnt扫描:进入 Step 6 时算子默认处于tileCnt=1串行基线(Step 2-4 期间配置)。Step 6 的工作是扫描tileCnt ∈ {1, 2, 4, 8, 16, 32},每个值跑一次 msprof 采集 + 后处理,对比整体 Task Duration 找最优。完整流程见pipeline_tuning.md§3 阶段 B + §6 决策树; - L2 cache flush 必须在主循环每轮触发:参考工程在 perf 主循环(
src/all_to_all_matmul.cpp的mode == "perf"分支)中每轮先调用heavy_add_kernel(256 MB bf16 全核扫一遍)刷 L2,再跑主 kernel,避免上一轮的热度污染本轮采集——所以 msprof 不需要--warm-up; - perf 模式默认跑 10 轮:msprof task-based 为每轮 main kernel 生成一条
op_summary_*.csv记录; - 多卡数据提取规则:每卡取最后 5 次 main kernel 的 Task Duration 求平均 → 4 卡平均值取最大值作为整体性能(多卡并行由最慢卡决定)。
门禁
docs/perf/round_NNN/存在且包含 4 个PROF_*子目录(每卡一份);extract_perf.py输出每卡rank_avg与整体maxTask Duration;- 最优
tileCnt与对应整体 Task Duration 已写入 DESIGN.md "性能调优记录"; - 若整体 Task Duration 与理论耗时差距 >50% → 视为性能不达标,检查通算流水是否真的并行(AIV time vs AIC time)。
Step 7:完成汇报
CANNBot 主控汇总以下信息给用户:
- 最终判定:PASS / PASS WITH NOTES
- 总分:Reviewer 100 分制
- 代码路径:
operators/{op_name}/ - 性能概要:Task Duration、主导流水(MC2 通常 AIC cube 主导)、通信隐藏率(AIV 与 AIC 重叠度)
- 关键问题列表:Step 4~5 期间遗留的 NOTE
【免费下载链接】cannbot-skillsCANNBot 是面向 CANN 开发的用于提升开发效率的系列智能体,本仓库为其提供可复用的 Skills 模块。项目地址: https://gitcode.com/cann/cannbot-skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考