Files
matmul-analysis/BMM/BMM_Theory/README.md
admin ec4fee99b8 Fix #40: 切换 Cube 算力为白皮书 Cube-only 口径 (单核统一 13.5T)
用户裁决: cube_peak_tflops 取白皮书表3-1 "Cube算力" 单行 (不含 Vector)。

- 数值: 950PR 486->432, 950PR_C28 425->378, 950DT 547->486,
  950DT_C32 486->432, 950DT_C28 425->378; 单核全系列精确 13.5T
  (16^3 MAC/拍 x 1.65GHz), 28 核档 0.06% 取整偏差随之消失
- 传导 (无结构改动, 全部经 q16/q_cube/r16 派生):
  MMAD 时延 x486/432 (+12.5%); R16 607.5->540 (MergeBatch 条件5/b0 上限);
  StreamK θ_c 12.24->10.9; ASW 面积/周长分界 93.5->83.1, MMAD/FIX 304->270
- 文档同步: README, docs/00 (R16 公式), 04 (607.5 实例), 05 (硬件事实/复核算例),
  06/07 (翻出阈值 187->166), 05_StreamK (θ_c 及 K 阈值 396->360);
  理论归档 (BMM算子优化分析_Release/) 与历史测评报告不动
- 验证: 单测 88/88; examples 重生成 —— recommend 27/44 行变化
  (计算Bound 行精确 +12.5%; b8_m32768_n2048_k512 瓶颈 MTE2->MMAD 翻转;
  17 行访存主导不变), plans.csv 仅 merge_demo_k_trunc note 的算存比上限
  23.7->21.1 一处文案; 压力回归 10000 例干净, MergeBatch 386->392 /
  IterBatch 2389->2384 (R16 下移致 b0 上限收小, 边界 case 换边, 预期行为)
2026-09-09 11:05:21 +08:00

121 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# BMM_Theory — batch_mat_mul_v3 理论最优实现分析软件
> 目标芯片: Ascend950PR (DAV_3510) | 算子: batch_mat_mul_v3 | 实现: Python 3
>
> 理论依据: 《BMM算子优化分析 v0.98》《MergeBatch_vs_IterBatch分析 v1.1》《BMM尾轮处理策略对比分析 v1.5》
## 这是什么
对任意 BMM (BatchMatMul) case, 回答两个问题:
1. **理论最优实现方案是什么** —— 该走哪个分支 (转Matmul/特殊分支/MergeBatch/IterBatch/StreamK/ASW_Basic), 核间怎么切, 核内 tile 怎么取, Cache/流水怎么配;
2. **这个实现方案在 NPU 上跑得怎么样** —— 各级硬件 (MTE2 搬入 / Cube 计算 / Fixpipe 搬出 / StreamK 归约) 时延多少, 谁是瓶颈, 怎么优化.
与 ops-nn 源码的关系: 源码是"当前实现", 本软件是"理论最优"——用于评估源码方案离理论上限有多远、瓶颈在哪里.
## 快速上手
```bash
# 无需安装, 在项目根目录直接运行 (Python >= 3.8, 仅标准库)
# 模式 1: 方案推荐 —— 输入 case, 输出理论最优方案 + 时延评估
python -m bmm_theory recommend examples/cases_demo.csv -o result.csv --plans plans.csv -v
# 模式 2: 方案评估 —— 输入 case + 自己的实现方案, 评估硬件表现与瓶颈
python -m bmm_theory evaluate examples/cases_demo.csv examples/plans.csv -o eval.csv -v
# 跑单元测试
python -m unittest discover -s tests -v
```
### case 输入 csv 格式
| 列名 | 含义 | 缺省 |
|---|---|---|
| case_id | 标识 | case_行号 |
| batch_a, batch_b | A/B 的 batch 维 | 1 |
| m, n, k | 矩阵维度 | 1 |
| dtype_a, dtype_b, dtype_c | 数据类型 (bf16/fp16/fp8/fp32) | bf16 |
| trans_a, trans_b | 是否转置 | 0 |
| has_bias | 是否有 bias | 0 |
| deterministic_level | 确定性等级 (>=2 禁用 StreamK) | 0 |
`examples/cases_demo.csv` 里有一份覆盖各分支的示例.
### 输出
- `result.csv`: 每行一个 case —— case 参数 + `plan_*` 方案字段 + 时延评估 (`t_mte2/t_mmad/t_fixpipe/t_total` 等, 单位秒) + `bottleneck` 瓶颈级 + `bound_type` Bound 类型 + `advice` 仲裁过程与优化建议;
- `plans.csv` (可选): 纯方案表, 标准结构体 `ImplPlan` 的全部字段, 可直接作为模式 2 的输入.
### 时延模型要点 (读结果前必看)
- **GM 是读写共享总线 (1.6TB/s)**: MTE2 的 GM 读与 Fixpipe 直写 GM 并发时按 **(读+写)/1.6TB/s 累加**计入 MTE2 搬移链 (issue#23);
- **搬入 MTE2 分两段、同链相加**: `t_mte2_gm` (首读按 GM 带宽; 随路驻留 L2 不重复累加) + `t_mte2_l2` (共享块驻留 L2 后被其它核重复读, 按 L2 读口 5.2TB/s) + DMA 命令开销 (issue#24; **T_cmd 默认 0**, 未标定按 0 处理, issue#36);
- **搬移效率模型 (issue#36)**: 切B 两分支 (IterBatch/MergeBatch) 的 GM→L1 数据时延按单命令 tile 效率加权 —— eff = min(1, tile/min_TileSize), tile = nValue×dValue×dtype 达 16KB 饱和; **MergeBatch 合并 b0 个 batch 使单块 tile 放大 b0 倍, 即便 T_cmd=0 也比 IterBatch 逐 batch 搬移效率高** (堆叠方向视转置: A ND 非转置沿 M(nValue), B ND 非转置沿 N(dValue)); 只影响时间列, GM 字节量不变;
- **Cube 计算** `t_mmad`: 芯片算力 = 白皮书 Cube-only 432 TFLOPS (单核 13.5 TFLOPS, issue#40), MergeBatch 冗余计算计入;
- **Fixpipe 搬出**: 直写 GM 计入 GM 共享总线; 驻留 L2 走 5.2TB/s 写口 (独立计时); 数据量按 **C 矩阵 dtype** 计 (fp16/fp8 随路转换减半); StreamK 部分和按 4B (L0C dtype);
- **总时延** `t_total = max(MTE2搬移链, MMAD, Fixpipe-L2) + t_drain` (稳态取最大 + 末级排空暴露; REDUCE 串行追加);
- **GM 读取下限**: 每输入字节至少从 GM 读一次 (R1); L2 只吸收"驻留后的再次读取"; 整 case 输入+输出 ≤ L2 时 GM 恰读一次、输出全驻留 L2 (issue#29 设计文档 docs/05);
- **Fixpipe 输出落点**: 整 case (输入+输出+workspace) 可驻留 L2 → 输出写 L2 写口 5.2TB/s、GM 写流量 0; 否则输入优先保 L2, 输出直写 GM 计入共享总线 (issue#30);
- **算力按输入 dtype**: Cube BF16/FP16 432TFLOPS 为基准 (Cube-only 口径, 白皮书表3-1 "Cube算力" 单行, issue#40), fp8=2x/fp4=4x (白皮书), fp32=1/2 (假设待标定); AIV 逐元素通量同理 (issue#28);
- **瓶颈交换**: 搬移瓶颈可牺牲算力换搬移效率 (MergeBatch), 计算瓶颈可牺牲搬移换计算效率 (ASW_Basic 切 M/N).
## 目录结构
```
BMM_Theory/
├── README.md # 本文档 (用法)
├── bmm_theory/ # 软件包
│ ├── __main__.py # CLI 入口 (recommend / evaluate)
│ ├── models.py # 数据模型: BmmCase / ImplPlan(标准结构体) / HardwareTiming
│ ├── hardware/ # 硬件参数表 (NpuSpec; 950PR 32/28核 + 950DT 36/32/28核,
│ │ # SPECS/get_spec 索引, 默认 ASCEND950PR; 换芯片只加这份)
│ ├── timing.py # 时延评估引擎 (MTE2/Cube/Fixpipe/Reduce 模型)
│ ├── constraints.py # 单一约束源 (生成与校验共用, L0C/L0A/L0B/L1/dValue/核数)
│ ├── router.py # 分支决策路由 + 重叠区仲裁 + 生成后自检
│ ├── evaluator.py # 方案评估器 (约束校验 + 瓶颈分析)
│ ├── io_csv.py # csv 输入输出
│ └── branches/ # 六分支理论脚本 (全部已实现)
│ ├── merge_batch.py # MergeBatch
│ ├── iter_batch.py # IterBatch (a/b/c/d 四形态)
│ ├── to_matmul.py # 转Matmul
│ ├── special.py # 特殊分支 (K=0/1, AIV 通路)
│ ├── stream_k.py # StreamK (切K + 归约)
│ └── asw_basic.py # ASW_Basic (含降核/swizzle/L2分组/尾轮决策)
├── docs/ # 文档 (架构 + 理论梳理 + 软件测评)
│ ├── 01_软件架构.md
│ ├── 02_分支理论/
│ │ ├── 00_总纲_分支决策树.md
│ │ ├── 01_MergeBatch分支.md
│ │ ├── 02_IterBatch分支.md
│ │ ├── 03_转Matmul分支.md
│ │ ├── 04_特殊分支.md
│ │ ├── 05_StreamK分支.md
│ │ ├── 06_ASW_Basic分支.md # 尾轮策略已内化为其必要环节
│ │ └── 07_尾轮处理策略.md # 尾轮完整推导 (参考)
│ └── 03_测评报告/ # 外部测评报告 (v1.0/v2.0 及后续复评)
│ └── 05_L2驻留GM读写与dtype算力口径_设计分析.md # GM/L2/输出落点/dtype算力统一口径 (issue#27-#30)
├── examples/ # 示例输入输出
└── tests/ # 单元测试 (固化文档边界 case + issue 回归)
```
**Python 版本**:实测通过 3.12(本机)与 3.14(测评环境);代码用 `from __future__ import annotations` 兜底注解,逻辑仅用标准库。建议 3.10+。
## 当前进度与路线图
| 分支 | 进入条件 | 方案生成 | 时延评估 | 状态 |
|---|---|---|---|---|
| MergeBatch | ✅ | ✅ | ✅ | 完成 |
| IterBatch (a/b/c/d 四形态) | ✅ | ✅ | ✅ | 完成 |
| 转Matmul | ✅ | ✅ (折叠+粗估) | ✅ (粗估) | 完成, 折叠后 Matmul 精切待 MM 体系打通 |
| 特殊分支 (K=0/1) | ✅ | ✅ | ✅ | 完成 |
| StreamK | ✅ | ✅ | ✅ (含归约) | 完成 |
| ASW_Basic (含降核/swizzle/L2分组/尾轮决策) | ✅ | ✅ | ✅ | 完成, 尾轮已内化 (默认方案B, 周长型A1b) |
## 设计原则
1. **以理论分析文档为准**——源码实现仅作对照, 不作为依据;
2. **参数表与逻辑分离**——换芯片只换 `hardware/` 下的参数表, 分支逻辑不动;
3. **结构体标准化**——`ImplPlan` 是推荐输出与评估输入的统一格式, 字段与理论文档符号一一对应;
4. **可验证**——文档中的典型边界 case 全部固化进 `tests/`, 改动不破结论.