- 数据源: 昇腾950_NPU架构白皮书 表3-1 (系列 SKU) / 表4-2 (Memory 层次) - 新增 hardware/ascend950dt.py: ASCEND950DT (36AIC/72AIV, HBM 4TB/s 144GB, L2 128MB 主bin) + ASCEND950DT_C32 + ASCEND950DT_C28 - ascend950pr.py: 新增 ASCEND950PR_C28 (28核, 1.4TB/s, L2 112MB) 与 gm_capacity_gb 信息字段; 注明 cube_peak_tflops 口径 (= 白皮书 "Cube+Vector 总算力" 行, 与 Cube 单行 432 的 12.5% 偏差待用户裁决) - __init__.py: SPECS 注册表 + get_spec(name), 默认仍为 ASCEND950PR, 现有 import 与调用点零改动 - 共架构交叉验证: 单核 Cube 13.5T (432/32=486/36), Vector fp32 27T/64核≈30T/72核 -> 128lane@1.65GHz; 表4-2 L1/L0/UB 各档一致 - docs/01_软件架构 + README 硬件层说明更新 - tests: TestIssue38 六例 (默认不变/注册表/DT派生量/AIV白皮书验证/DT路由 冒烟/未知KeyError); 87/87 通过; examples 44例 0 diff; 压力回归 10000 例干净, 分支分布与上轮逐数一致
7.8 KiB
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 + 950PR 32/28核 SKU │
│ ├─ ascend950dt.py 950DT 36/32/28核 SKU (issue#38) │
│ └─ __init__.py SPECS 注册表 + get_spec(name) │
├─────────────────────────────────────────────────────────┤
│ 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 分支 = 自包含插件
每个分支类实现三个方法:
class Branch:
def check_conditions(case) -> list[ConditionCheck] # 逐条进入条件判定 (可解释)
def make_plan(case) -> ImplPlan # 理论最优方案生成
def evaluate(case, plan) -> HardwareTiming # 时延评估
新增分支 = 在 branches/ 下加一个文件 + 在 router.py 注册。互不依赖,可独立迭代。
3.3 硬件参数与逻辑分离
hardware/ 的 NpuSpec 集中所有芯片常数(核数/算力/各级容量/带宽/搬移效率经验值/T_cmd)。所有分支通过 self.spec 取参数——换芯片时新增一份参数表即可,分支逻辑零改动。已注册 SKU(issue#38,昇腾950 白皮书表3-1/表4-2):Ascend950PR(32核主bin)/Ascend950PR_C28 与 Ascend950DT(36核主bin)/Ascend950DT_C32/Ascend950DT_C28,经 hardware.SPECS / get_spec(name) 索引,默认仍为 ASCEND950PR。
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#9):REDUCE 默认串行追加(体现在 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 < K、K 段为搬移连续维)时 128B 下限才生效;K 整驻留(k_l1 ≥ K)时连续维是 M/N,豁免 K 向下限。
4. 扩展指南(后续迭代)
当前六分支已全部实现(转Matmul / 特殊 / MergeBatch / IterBatch / StreamK / ASW_Basic)。后续方向:
- 转Matmul 精切: 当前折叠后只粗估(
to_matmul.py::evaluate按 Matmul 总量),接入 MM 理论体系做精确切分。 - 换芯片:
NpuSpec(name=..., ...)派生实例并注册进hardware.SPECS(参考ascend950dt.py),接口不变;默认规格恒为ASCEND950PR。 - 标定 T_cmd: 当前按 0 处理 (未标定, issue#36; MergeBatch 合并收益已由 move_eff 搬移效率模型刻画, 不依赖 T_cmd 估计值), 实测后改
t_cmd_ns一处即可。 - 新分支: 在
branches/下加一个文件实现三接口 + 在router.py注册 + 在evaluator._BRANCH_EVAL注册;约束一律走constraints.py,不在分支内另造规则。