Files
matmul-analysis/BMM/BMM_Theory/docs/01_软件架构.md
admin b0b48b9073 Fix #36: MergeBatch 合并搬移效率收益建模 (move_eff) + t_cmd_ns 置 0
用户澄清: MergeBatch vs IterBatch 的本质区别不只是 DMA 命令数 —— 合并 b0 个
batch 的左/右矩阵一起搬入 L1, 使单块 tile = nValue*dValue*dt 放大 b0 倍 (堆叠
方向视转置: A ND 非转置沿 M(nValue), B ND 非转置沿 N(dValue)), 搬移效率更高,
即便 T_cmd=0 也有效益。

- models.move_eff: 单命令搬移效率 eff = min(1, tile/min_TileSize) (16KB 饱和,
  与进入条件4效率下限语义同源); gm_move_time 按 A/B 两侧字节加权
  t = (V_A/eff_A + V_B/eff_B)/BW_gm; 只影响时间列, GM 字节量仍 = V_in
- IterBatch: l1_form 补驻留侧返回; move_tiles 分侧口径 (a/b 双侧整K, c 驻留侧
  整K+对侧k_l1, d 双侧k_l1), evaluate 接入效率加权
- MergeBatch: 合并 tile 放大 b0 倍接入效率加权; beats_iterbatch 净收益 =
  命令节省(cmds差×T_cmd) + 效率节省(t_data差) − drain惩罚, K截断且效率打平且
  T_cmd>0 时严格退化为 v1.1 §4.5 闭式; 退役 T_cmd<=0 策略特判
- router: 退役 "T_cmd<=0 策略优先 MergeBatch" 覆盖, 时延模型统一终审
- hardware: t_cmd_ns 50 -> 0 (未标定按 0; 合并收益不再依赖 T_cmd 估计值)
- 作用域: 仅切B 两分支接入 (逐命令 tile 小、效率差显著); ASW/StreamK 单命令
  tile 通常已饱和, 极端小 tile 走 issue#34 效率降级标注通道
- 用户 case 家族 B=128,M=1~16,N=128,K=512: m=1~8 -> MergeBatch (效率节省
  ~0.61us > drain), m=16 -> IterBatch (iter A tile 恰达 16KB 饱和, 效率打平,
  drain 决定); 分界与时延全家族一致
- demo: merge_demo_k_trunc 形状 (2048,32,32,256)->(2048,16,64,128) (原形状
  两侧 tile 均已 16KB 饱和, t_cmd=0 下无收益转 IterBatch; 新形状 iter A tile
  4KB eff=0.25 vs 合并 16KB eff=1.0, 保持 MergeBatch 胜出演示且仍 K截断)
- 测试: 74/74 (新增 TestIssue36 5 例: 效率曲线/字节不变/效率差胜出/家族;
  TestArbitration/TestZeroCmdHandling 按 t_cmd=0+效率语义重写; TestIssue35
  家族期望更新)
- 文档: 01_MergeBatch §4/§5 效率模型+泛化净收益; 02_IterBatch 口径注;
  00_总纲胜出条件; 01_软件架构 T_cmd 标定说明; 05 时间列效率口径注; README 要点
- 验证: examples 重生成可复现 0 diff; 压力 10000 例 0 崩溃/0 NaN/0 违规/
  0 GM<V_in, 七分支覆盖 (MergeBatch 386 例)
2026-09-07 21:09:49 +08:00

116 lines
7.4 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 软件架构
## 1. 分层视图
```
┌─────────────────────────────────────────────────────────┐
│ CLI (__main__.py) recommend / evaluate 两种模式 │
├─────────────────────────────────────────────────────────┤
│ 应用层 │
│ ├─ router.BranchRouter case -> 分支决策 + 方案 + 时延 │
│ └─ evaluator.PlanEvaluator (case, 方案) -> 校验 + 时延 │
├─────────────────────────────────────────────────────────┤
│ 分支层 (branches/) —— 每个分支一个文件, 三个接口 │
│ ├─ merge_batch.py MergeBatchBranch │
│ ├─ iter_batch.py IterBatchBranch │
│ ├─ to_matmul.py ToMatmulBranch │
│ ├─ special.py SpecialBranch │
│ ├─ stream_k.py StreamKBranch │
│ └─ asw_basic.py AswBasicBranch │
│ 统一接口: check_conditions / make_plan / evaluate │
├─────────────────────────────────────────────────────────┤
│ 模型层 │
│ ├─ models.py BmmCase / ImplPlan / HardwareTiming │
│ ├─ timing.py MTE2 / MMAD / Fixpipe / Reduce 时延引擎│
│ └─ constraints.py 单一约束源 (生成与校验共用) │
├─────────────────────────────────────────────────────────┤
│ 硬件层 (hardware/) │
│ └─ ascend950pr.py NpuSpec 参数表 (换芯片只换这份) │
├─────────────────────────────────────────────────────────┤
│ IO 层 (io_csv.py) case/plan/result 的 csv 读写 │
└─────────────────────────────────────────────────────────┘
```
## 2. 两种工作模式的数据流
**模式 1: 方案推荐 (recommend)**
```
cases.csv ──> load_cases ──> BranchRouter.route(case)
│ 决策树: 前置归约 -> B>=C? -> IterBatch/MergeBatch 仲裁
ImplPlan (标准结构体) + HardwareTiming
result.csv (case + plan_* + 时延 + 瓶颈 + 建议)
plans.csv (纯方案表, 可作模式 2 输入)
```
**模式 2: 方案评估 (evaluate)**
```
cases.csv + plans.csv ──> PlanEvaluator.evaluate(case, plan)
│ 1. 硬件约束校验 (L0C/L0A/L0B/L1 容量, dValue, 核数)
│ 2. 按方案分支调用对应时延模型
│ 3. 瓶颈分析 + 优化建议
eval.csv (feasible / violations / 时延 / advice)
```
## 3. 关键设计决策
### 3.1 ImplPlan 是系统的"通用货币"
推荐模式的输出与评估模式的输入共用同一个结构体 `ImplPlan``models.py`),字段分四组:
| 组 | 字段 | 说明 |
|---|---|---|
| 分支与核间切分 | branch, used_core_num, split_b, m_cnt, n_cnt, grid_k, core_map | 第一性问题: 核间怎么分 B/M/N/K |
| 核内 tiling | b_core, merge_b0, single_core_m/n/k, k_l1, b_l1, l1_form, base_m/n/k | 第二性问题: 核内 tile |
| Cache 策略 | l2_policy_in, l2_policy_out, swizzle_w, workspace_bytes | L2 驻留/直写、滑窗 |
| 流水策略 | tail_strategy, fixpipe_unitflag, out_dtype_bytes | 尾轮 A0/A1a/A1b/方案B、unitflag |
`to_row()` / `from_row()` 负责与 csv 的双向转换,字段名即 csv 列名。
### 3.2 分支 = 自包含插件
每个分支类实现三个方法:
```python
class Branch:
def check_conditions(case) -> list[ConditionCheck] # 逐条进入条件判定 (可解释)
def make_plan(case) -> ImplPlan # 理论最优方案生成
def evaluate(case, plan) -> HardwareTiming # 时延评估
```
新增分支 = 在 `branches/` 下加一个文件 + 在 `router.py` 注册。互不依赖,可独立迭代。
### 3.3 硬件参数与逻辑分离
`hardware/ascend950pr.py``NpuSpec` 集中所有芯片常数(核数/算力/各级容量/带宽/搬移效率经验值/T_cmd。所有分支通过 `self.spec` 取参数——换芯片时新增一份参数表即可,分支逻辑零改动。
### 3.4 时延引擎统一在 timing.py
分支不各自造轮子,统一调用 `timing.py` 的四个函数:
- `eval_mte2(move)` —— GM/L2 两段搬入 + DMA 命令开销
- `eval_mmad(flops)` —— Cube 计算
- `eval_fixpipe(bytes, to_l2)` —— 搬出(直写 GM 或驻留 L2
- `eval_streamk_reduce(...)` —— StreamK 归约(部分和 4B 驻留 L2、AIV 求和)
`assemble_timing(...)` 汇总并判瓶颈。**归约计账约定**issue#9REDUCE 默认串行追加(体现在 `t_drain`),不进稳态 `max()`;仅当显式声明可流水掩盖(`reduce_serial=False`)时才进 `max()`。带宽模型:每核独立 DMA 引擎、带宽按核数配平(尾轮文档 §2.4),活跃核数 < C 时聚合带宽按比例下降
### 3.5 单一约束源constraints.py
约束知识L0C/L0A/L0B/L1/dValue/min_TileSize/核数**只有一个事实来源**`constraints.check_plan_constraints(case, plan)`生成侧recommend `_wrap_checked` 自检与评估侧evaluate `_check_constraints`共用同一函数保证"推荐方案 vs 自带评估器"口径一致不再出现生成说可行校验说不可行的矛盾
生成侧的 tile 收敛辅助`clamp_base_k` / `clamp_base_mn_l0c`也在此模块各分支 `make_plan` 调用同源函数保证生成的 tile 不越界dValue 口径裁定issue#6仅当 K 被切分成段k_l1 < KK 段为搬移连续维 128B 下限才生效K 整驻留k_l1 K时连续维是 M/N豁免 K 向下限
## 4. 扩展指南(后续迭代)
当前六分支已全部实现转Matmul / 特殊 / MergeBatch / IterBatch / StreamK / ASW_Basic)。后续方向
1. **转Matmul 精切**: 当前折叠后只粗估`to_matmul.py::evaluate` Matmul 总量接入 MM 理论体系做精确切分
2. **换芯片**: 复制 `hardware/ascend950pr.py` 改常数`NpuSpec` 接口不变
3. **标定 T_cmd**: 当前按 0 处理 (未标定, issue#36; MergeBatch 合并收益已由 move_eff 搬移效率模型刻画, 不依赖 T_cmd 估计值), 实测后改 `t_cmd_ns` 一处即可
4. **新分支**: `branches/` 下加一个文件实现三接口 + `router.py` 注册 + `evaluator._BRANCH_EVAL` 注册约束一律走 `constraints.py`不在分支内另造规则