Fix #27-#30: dtype感知算力(Cube/AIV速率表) / GM首读下限与整芯片字节列口径+设计文档 / Fixpipe输出落点R4(整case驻留L2否则直写GM) / MergeBatch Cube公式复核注释

- docs/05_L2驻留GM读写与dtype算力口径_设计分析.md: R1-R6公理、S_A/S_B/S_C场景、输出落点R4、dtype速率表(白皮书出处+待标定假设)、逐分支GM/L2归属表 (issue#29/#30 先文档后代码)
- hardware: CUBE_DTYPE_FACTOR(f16/bf16=1, fp8=2x, fp4=4x, fp32=1/2假设) + AIV_DTYPE_FACTOR + q_cube/aiv_elem_rate (issue#28)
- 全分支 t_mmad/t_comp/drain/尾轮主导项/θ_c/R16 语义按输入dtype取算力; 混精度取慢侧; StreamK归约保持fp32(AIV fp32部分和)
- Fixpipe输出落点R4: to_l2 <=> V_in+V_out(+workspace)<=L2; 否则直写GM计入共享总线; ASW场景改S_A整case全驻留(原单batch驻留判定漏计整case输出累积逐出)
- 字节列统一整芯片口径(gm/l2/fix/cube_flops), dma_cmd_count注明单核; GM>=V_in不变量入测试; MergeBatch每步flops=2(b0M)(b0N)K公式注释显式化(#27复核与CSV一致无数值改动)
- tests 39->49 全过; 双压力seed7/6000+seed2024/4000: 0违规/0占位/0NaN/0GM<输入; examples三件套重生成且可复现0diff
This commit is contained in:
2026-09-04 16:26:10 +08:00
parent 4843053ad3
commit b9e07edc1d
15 changed files with 793 additions and 239 deletions

View File

@@ -0,0 +1,197 @@
# 05 L2 驻留、GM 读写与 dtype 算力口径 — 设计分析
> 关联 issue: #27 (MergeBatch Cube 复核) / #28 (dtype 感知算力) /
> #29 (GM 读取量下限 + L2 驻留工作集) / #30 (Fixpipe 输出落点)
>
> 状态: 设计文档先行, 代码按本文档落地 (2026-06 评审轮)。
> 本文档是 GM/L2/输出计账与算力口径的**单一语义来源**; 各分支 evaluate/生成注释以本文档为准。
---
## 0. 本轮的四个问题与结论摘要
| # | 问题 | 结论 | 落地 |
|---|---|---|---|
| #27 | MergeBatch Cube 时延 "每次 b0 个 batch, flops=2·b0M·b0N·K, 共 b_core/b0 次" | **公式与代码一致** (总 flops = b_core·b0·2MNK, 证明见 §6); 无计算改动 | 注释显式化; 暴露的"字节列每核/芯片口径混用"随 #29 统一 |
| #28 | 估算时延恒用 BF16 Cube / fp32 AIV 算力 | **确认错误** | §2 dtype 感知速率表 + 全链路替换 |
| #29 | GM 读取量"小于输入数据量" | 计算层面各分支 GM ≥ 输入一次 (逐分支表见 §5); **真问题**: ① 字节列每核/芯片口径混用导致比对失真; ② 缺整 case 驻留边界与统一驻留判定 | §3 公理化 + §4 场景模型 + 芯片口径列统一 + GM≥输入不变量测试 |
| #30 | Fixpipe 输出落点 (默认写 L2, 容量不足才写 GM) | **确认错误** (Iter/Merge/特殊恒直写 GM; ASW 场景 A 按单 batch 判定, 整 case 输出累积必逐出) | §4.2 输出落点规则 |
---
## 1. 硬件事实 (Ascend950PR, 与 hardware/ascend950pr.py 对应)
- GM (HBM): **1.6TB/s, 读写共享总线** —— 同一时刻读与写累加计时 (issue#23 已落地)。
- L2: 128MB, **5.2TB/s, 读口/写口各自独享** —— L2 重复读(读口)与 Fixpipe→L2 写(写口)互不竞争 (issue#23 已落地)。
- 输入首访一律走 GM 带宽计一次, 不叠加 L2 (issue#24 已落地); L2 只吸收"驻留后的再次读取"。
- Cube 算力分精度 (白皮书: FP8/MXFP8/HiF8 = 2×FP16, MXFP4 = 4×FP16; 16bit 档 = 基准):
BF16 486 TFLOPS/芯片 (=15.1875 TFLOPS/核)。FP32/TF32 同代比值白皮书未给 → **假设 ½, 待实测标定** (见 §2 假设表)。
- AIV (Vector): 64 核 × 128 fp32 lane/拍 × 1.65GHz = 13.5T 元素/s (fp32 档)。
---
## 2. dtype 感知算力 (issue #28)
### 2.1 速率表 (因子, 相对基准档)
Cube 因子 (相对 BF16, 同倍率作用于整芯片与单核):
| dtype | 因子 | 依据 |
|---|---|---|
| bf16 / fp16 | 1.0 | 基准档 (950 同速) |
| fp32 / tf32 | 0.5 | **假设**: 白皮书仅述 FP16/FP32 单核较上代均 +100%, 未给同代比值; 按 DaVinci 惯例 FP32 累加通量减半。待 msProf 实测标定 |
| fp8 / fp8_e4m3 / fp8_e5m2 | 2.0 | 白皮书: FP8 = 2×FP16 |
| int8 | 2.0 | **假设** 同 FP8 (8bit 整数张量档), 待实测 |
| fp4 / fp4_e2m1 | 4.0 | 白皮书: MXFP4 = 4×FP16; 普通 fp4 按 MXFP4 假设, 待实测 |
AIV (Vector) 逐元素通量因子 (相对 fp32 lane 基准):
| dtype | 因子 | 依据 |
|---|---|---|
| fp32 / tf32 | 1.0 | 基准 (128 lane/拍/核) |
| fp16 / bf16 | 2.0 | **假设** 16bit 双元素/lane, 待实测 |
| fp8 / int8 | 4.0 | **假设** 8bit 四元素/lane, 待实测 |
| fp4 | 8.0 | **假设** 待实测 |
A/B dtype 不一致 (混精度): Cube 取**较慢一侧**的因子 (max(字节数) 侧, 即 min(因子))。
StreamK 归约是对 **fp32 部分和**求和 → AIV 归约恒按 fp32 档 (因子 1.0), 不随输入 dtype 变。
### 2.2 替换点 (全部时延估算)
| 位置 | 现状 | 改为 |
|---|---|---|
| 各分支 t_mmad / t_comp_chunk / drain / 尾轮决策主导项 | flops / spec.q16 | flops / spec.q_cube(dtype_a, dtype_b) |
| MergeBatch beats_iterbatch 阈值中的 T_comp | q16 | 同上 (该分支 A/B 同 dtype, 简化为 dtype_a) |
| special K=1 t_compute (逐元素乘) | b·m·n / spec.q_aiv (fp32) | b·m·n / spec.aiv_elem_rate(dtype_in) |
| StreamK θ_c (归约代价系数) | q16(bf16) | q_cube(输入 dtype) (AIV 侧仍 fp32) |
| R16 平衡点 (MergeBatch 进入条件 5 / b0 算存比上限) | r16(bf16 基准) | r16_for(dtype) |
| 入口条件/生成侧 | — | 同步按 §2.1 因子 (dtype 只影响时延, 不改变分支结构) |
---
## 3. 存储口径公理 (issue #29)
记号:
- V_in = 输入存储总量 = batch_a·M·K·dt + batch_b·K·N·dt (广播前实际存储), V_out = batch_c·M·N·out_dt;
- a_b = M·K·dt (单 batch A 字节), b_b = K·N·dt (单 batch B 字节)。
- **R1 (GM 首读下限)**: 每个输入字节最初在 GM, 至少从 GM 读一次 → **GM_read ≥ V_in**
违反即模型 bug (统一用测试锁死)。
- **R2 (L2 只吸收驻留后的重复读)**: 同一字节的第 2..n 次访问, 仅当两次访问之间该字节仍驻留 L2
(所在"复用窗口"的工作集 ≤ L2 减去其它占用) 才按 L2 读口计时; 否则按 GM 重读计时。
- **R3 (整 case 全驻留边界)**: V_in + V_out (StreamK 另加部分和 workspace) ≤ L2 时,
全程零逐出: GM_read = V_in (每字节一次), 全部重复读走 L2, 输出驻留 L2 (见 §4.2)。
- **R4 (输出落点)**: 见 §4.2。
- **R5 (输入工作集场景)**: 单 batch 输入 ≤ L2 → batch 内 tile 共享块重复读按 L2 计
(A 行块被 n_cnt 个列 tile 复用 → (n_cnt1) 次 L2; B 列块被 m_cnt 个行 tile 复用 → (m_cnt1) 次 L2);
单 batch 输入 > L2 → 分组执行 (工作集思想, §4.3)。
- **R6 (已知简化, 文档标注)**: ① 组内窗口复用未另计 (保守); ② BatchA≠BatchB (均 ≥2, 如 2 vs 64)
的广播/混合 batch 结构按"每 batch 独立矩阵"计 GM = b·(a_b+b_b), 是 V_in 的**保守放大**
(真实为 V_in + 共享矩阵跨 batch 重复读 ≤ 该值), 文档标注不做特殊建模; ③ K 切分 (k_L1<K)
chunk 搬运按整段 k_L1 (含末段 padding 上取), GM V_in 恒成立
### 3.1 逐分支 GM/L2 流量归属表 (现行模型正确性核查结果)
| 分支 | 结构 | GM 直读 | L2 重复读 | 核查 |
|---|---|---|---|---|
| IterBatch ( B) | batch 整驻留/ K; (batch, K段) 数据互不重叠 | V_in (+K padding) | 0 (L1 形态吸收核内复用) | GMV_in |
| MergeBatch | 合并组 (b0 batch) 一次搬入; K / K 均不跨段重读同一字节 | V_in (+K padding) | 0 | GMV_in |
| ASW ( M/N) | batch tile 共享行/列块 | 场景 B: V_in; 场景 C: r_gm·V_in | (n_cnt1a_b·b + (m_cnt1b_b·b (场景 A/B) | GMV_in (场景 C 只放大) |
| StreamK | 组内 K 段零重复读; 组间共享块同 ASW | V_in (命中时) | 组间共享块 (命中时) | |
| 特殊分支 K=1 | AIV 通路, 每元素一次 | V_in | 0 | |
| 转Matmul | 折叠单次 GEMM | V_in | 0 (Matmul 精切未展开) | |
**计算层面 GM 均 ≥ V_in**, 用户看到的 "GM < 输入" 来自**字节列每核/芯片口径混用**
(MergeBatch/IterBatch 记每核值 ×32 才是整芯片; ASW/StreamK 记整芯片值), 不是少算
统一为整芯片口径 (修正项 ①), 并加不变量测试 (修正项 ②), 补齐 R3 case 边界 (修正项 ③)。
---
## 4. 场景模型 (输入侧) 与输出落点 (issue #30)
### 4.1 场景判定 (对切 M/N 及切 B 分支共用; L2 为整芯片 128MB)
- **S_A case 全驻留**: V_in + V_out [+ workspace] L2 输出驻留 L2;
- **S_B batch 输入可驻留**: 不满足 S_A, a_b + b_b L2 输入 batch 内共享块重复读命中 L2;
- **S_C batch 输入超 L2**: a_b + b_b > L2 → 分组执行 (输入工作集切分), 组间落空回 GM。
判定顺序: S_A → S_B → S_C。(原 #24 场景 A 的"单 batch 输入+输出可驻留"判定被 S_A 取代:
整 case 输出跨 batch 累积时单 batch 判定不可靠, 见 #30。)
### 4.2 R4 输出落点规则 (取代一切"恒直写 GM / 单 batch 判定驻留")
> to_l2(输出写 L2 写口 5.2TB/s, GM 写流量=0, 异步回写不占算子时延 — #23 口径延续)
> ⟺ **V_in + V_out [+ StreamK workspace] ≤ L2** (整 case 判定)
> 否则输出**直写 GM**: 计入 GM 读写共享总线, 与读累加进 MTE2 搬移链 (#23 口径)。
理由: 输出字节只写一次无复用价值, L2 应优先保输入工作集 (输入存在重复读);
只有当"整 case 输入+输出"可同时全驻留时才值得让输出占 L2 (省掉整条 GM 写时延)。
各分支应用:
| 分支 | 原行为 | 新行为 |
|---|---|---|
| IterBatch / MergeBatch / 特殊分支 / 转Matmul | 恒 direct_gm | S_A 时 to_l2; 否则直写 GM |
| ASW | 场景 A (单 batch in+out 驻留) 时 to_l2 | S_A (整 case) 时 to_l2; S_B/S_C 直写 GM |
| StreamK | 归约内最终写回恒走 L2 | 最终写回按 S_A(+workspace); 不满足时写 GM (drain 内按 GM 带宽) |
### 4.3 场景 C 分组工作集 (沿用 #24 公式, 语义重申)
单 batch 输入超 L2 → 以 L2 为单 batch 活动窗口预算 D = L2 / (K·dt) (元素),
组 = m_grp × n_grp 个 tile, 组间共享块复用落空回 GM:
r_gm = (⌈n_cnt/n_grp⌉·M + ⌈m_cnt/m_grp⌉·N)/(M+N), GM = r_gm·V_in;
组内窗口复用未另计 (保守, R6①)。分组追求"最小 L2 替换": 一次只让一组的工作集占 L2。
### 4.4 字节列与计数列语义 (修正 ①, 整芯片口径)
输出 CSV 中数据量列一律为**整芯片**口径: gm_read_bytes / l2_read_bytes /
fixpipe_bytes / cube_flops = 整芯片量; 时延列 t_* 为墙钟时延 (已含核数折算);
dma_cmd_count 为**单核**命令数 (各核 DMA 引擎并行执行, 墙钟 T_cmd = 单核命令数 × t_cmd),
与字节列口径不同属, 单独标注。
---
## 5. 各分支 GM/输出计账公式落地 (与代码对应)
统一由 case 属性提供 V_in / V_out; 输出落点判断函数 `output_to_l2(case, spec, workspace)` (S_A)。
| 分支 | GM 读 (芯片) | L2 读 (芯片) | 输出 |
|---|---|---|---|
| MergeBatch | V_in (K截断); V_in·ceil(K/k_L1)·k_L1/K (L1绑定 padding, 模型按整段计) | 0 | S_A→L2 写口; else GM |
| IterBatch | V_in (a/b 形态); 同上 padding 式 (c/d) | 0 | 同 MergeBatch |
| ASW 切M/N | S_A/B: V_in; S_C: r_gm·V_in | S_A/B: b·[(n_cnt1)·a_b + (m_cnt1)·b_b] | S_A→L2; else GM |
| StreamK | V_in (组间共享命中) | b·[(n_cnt1)·a_b + (m_cnt1)·b_b] (命中时) | 最终写回: S_A(+ws)→L2; else GM |
| 特殊分支 | K=1: V_in; K=0: 0 | 0 | S_A→L2 写口; else GM (K=0 只有输出) |
| 转Matmul | V_in (折叠后) | 0 | S_A→L2; else GM |
时延计算: 全核并发时 t = 芯片字节 / 芯片带宽; 降核 (used < C) 时按 used×单核份额
(线性假设, issue#26 标注), Cube t = 芯片 flops / (used × q_cube(dtype))。
---
## 6. MergeBatch Cube 复核 (issue #27) — 证明
合并语义: A'[b0·M, K] @ B'[K, b0·N] 作为单次 GEMM, Cube 硬件计算**全网格**
(b0·M)×(b0·N) 输出 (含交叉项, 冗余比例 (b0²−b0)/b0² = (b01)/b0), 只保留 b0 个对角块
- 每次合并计算 (): flops_step = 2·(b0·M)·(b0·N)·K;
- 每核合并组数: b_core/b0;
- 总: flops = (b_core/b0)·2·(b0·M)·(b0·N)·K = **b_core·b0·2MNK** —— 与现行代码
`flops_pc = b_core·b0·2·m·n·k` 逐项相等, t_mmad = flops/Q16 不变
CSV 证据 (merge_demo_k_trunc, B=2048 M=N=32 K=256, b0=4, b_core=64):
flops_step = 2·128·128·256 = 8,388,608; 步数 16; 合计 134,217,728 = 代码值 = CSV cube_flops ;
t_mmad = 134,217,728 / 15.1875e12 = 8.837us = CSV t_mmad。**结论: 无需数值修改**;
若意图是"只算对角块"则与全网格 GEMM 语义冲突 (冗余消失, v0.98 § 理论前提需另行裁决)。
---
## 7. 变更影响与验证口径
1. 字节列整芯片化 (IterBatch/MergeBatch/special 数值 ×C 或按 b 直接计算);
2. S_A 判定下输出写 L2: case ( case 可全驻留) GM 写流量清零输出时延降为 L2 写口;
3. S_A 之外输出 GM 写流量如实计入共享总线 修正单 batch 驻留判定导致的漏计;
4. dtype 感知算力: bf16 案例数值零回退; fp32/fp8/fp4/… 案例时延按 §2.1 表修正;
5. 新增回归: GMV_in 不变量 (全分支随机集)、S_A 输出落点开关dtype 速率比例
fp32 Cube 时延 = bf16 2 字节列整芯片口径等;
6. examples 三件套重生成, 与模型改动前 diff 隔离后入库; 压力回归 0 违规/0 NaN