Fix #31/#32: 切B类GM每字节恰一次=V_in(去K切分整段上取) / ASW场景升级(单侧全驻留+对侧滑窗->S_B, S_C最小替换2D分组+窗口L2计账) / 06文档§3+Step5与docs/05同步

#31 IterBatch/MergeBatch: K切分各(batch,K段)互不重叠+驻留侧每batch一次+末段按实际剩余
    -> GM读取量=V_in(与L2容量无关), GM数据时延=V_in/W_GM; n_K仅决定DMA命令数(T_cmd)
    b64_m16_n256_k512 形态c: GM 25.07MB->17.83MB=V_in; 回归: 形态c/d非整除+L1绑定三类断言
#32 ASW: (1)S_B扩展单侧全驻留+对侧滑窗(a_b/b_b+2*对侧单块<=L2) -> GM=V_in, 6个场景C行回落S_B;
    (2)S_C在整L2容量约束下搜索最小GM=ceil(n_cnt/n_grp)a_b+ceil(m_cnt/m_grp)b_b(取代L2/2对半预算),
    并计组内窗口L2流量((n_cnt-ceil)a_b+(m_cnt-ceil)b_b), 与S_B'驻留命中走L2'口径一致;
    b8_m131072_n8192_k8192 GM倍率4.76x->3.88x(物理下界~3.9x, 双侧均超L2)
    大方形K行(如b128_m8192_n8192_k7168)由MMAD 253ms->MTE2(L2口)295ms: 共享块重复读1.38TB
    经L2读口5.2TB/s, 如实计账(原C窗口流量零计低估)
- docs/06 §3与Step5重写为S_A/S_B/S_C+两段链口径(旧r_in单段/除B/对半预算口径废弃)
- docs/05 R5/R6/§3.1/§4.1/§4.3/§5与docs/01、02(01_MergeBatch/02_IterBatch GM口径附注)同步
- tests 54/54; 压力seed7/6000+seed2024/4000: 0违规/0占位/0NaN/0GM<V_in; examples重生成0diff
This commit is contained in:
2026-09-04 17:12:47 +08:00
parent b9e07edc1d
commit 18f59599e7
11 changed files with 370 additions and 192 deletions

View File

@@ -56,6 +56,11 @@ $$T_{mb} = \underbrace{\frac{b_{core}}{b_0}\cdot n_K^m\cdot(T_{load}^m + T_{cmd}
L1 绑定情形搬移次数单次搬移量都与 IterBatch 相同只放大 drain——证明见 v1.1 §4.4
> **GM 数据量口径 (issue#31)**: 各 (合并组, K段) 的数据互不重叠, 每个输入字节恰好从 GM
> 读一次 —— K 截断与 L1 绑定两种情形的**芯片 GM 读取量都 = V_in** (末段按实际剩余计,
> 无 padding 上取)。上式的 T_load 级联只用于刻画命令/双缓冲调度结构: 数据时延按
> V_in/W_GM 计, n_K 只放大 DMA 命令项 (b_core/b₀ 或 b_core·n_K) × T_cmd。
## 5. MergeBatch vs IterBatch 净收益
$$\text{净收益} = \underbrace{b_{core}\Big(1-\frac{1}{b_0}\Big)T_{cmd}}_{\text{搬移命令节省}} - \underbrace{(b_0-1)(T_{comp}+T_{write})}_{\text{drain 惩罚}}$$

View File

@@ -40,6 +40,11 @@ $$T_{iter} = \underbrace{b_{core}\cdot n_K\cdot(T_{load} + T_{cmd})}_{\text{搬
每 batch 的 A[M,K]+B[K,N] 作为独立 DMA 操作搬入 L1源码 `ndNum = curIterBatchL1`,多块独立寻址)。
> **GM 数据量口径 (issue#31)**: 形态 a/b/c/d 的 K 段/驻留侧数据互不重叠、每个输入字节
> 恰好从 GM 读一次 (形态 c 的驻留侧每 batch 只搬一次; 切 K 末段按实际剩余计, 无 padding
> 上取) —— **芯片 GM 读取量 = V_in**, 与 L2 容量无关 (IterBatch 无 L2 级重复读)。
> n_K 只决定 DMA 命令数 (T_cmd 项) 与双缓冲调度, 不放大数据量; 数据时延按 V_in/W_GM 计。
## 6. 与 MergeBatch 的分界
见 [01_MergeBatch分支.md](01_MergeBatch分支.md) §4~5。IterBatch 在 **L1 绑定情形恒优**MergeBatch 仅在 K 截断且 b_core 足够大时胜。

View File

@@ -20,15 +20,29 @@ ASW_Basic 是 BMM 的**兜底分支**——核间切 M/N或混合切
## 3. 时延建模
核间切 M/N不切 K每核处理若干 [singleCoreM, singleCoreN] 输出块
核间切 M/N不切 K每核处理若干 [singleCoreM, singleCoreN] 输出块 batch
A 行块被 n_cnt 个列 tile 共享B 列块被 m_cnt 个行 tile 共享issue#24 用户口径
最新场景口径见 issue#32 docs/05 §4
$$T = \max(T_{MTE2},\; T_{MMAD},\; T_{FIX}) + T_{drain}$$
其中 `T_MMAD = 2BMNK/(C·Q16)``T_FIX = B·MN·outB/(C·W_pc)` 与分配策略无关——**分配策略只影响 T_MTE2**通过 L2 命中率影响有效 GM 带宽
- `T_MMAD = 2BMNK / (used·Q16(dtype))` —— 与分配策略无关Q16 按输入 dtype 分档 (issue#28)
- **MTE2 两段搬移链**issue#23/#31/#32GM 为读写共享总线:
- `t_gm = S_in^GM / W_GM`GM 直读量首读 + 落空重读与输出直写 GM 并发时
读写累加输出落点见 docs/05 §4.2 R4
- `t_l2 = S_in^L2 / W_L2`L2 重复读量共享块驻留后其余次读取5.2TB/s 读口独享
- MTE2 = t_gm + t_l2 + DMA 命令开销
- `T_FIX`R4 输出落点—— case 输入+输出 L2 时写 L2 写口异步回写不占算子时延
否则直写 GM 计入共享总线issue#30)。
$$T_{MTE2} = \frac{S_{in}^{GM}}{C\cdot BW_{pc}},\qquad S_{in}^{GM} = r_{in}\cdot S_{in}$$
**GM/L2 流量归属 —— L2 场景判定**与代码 `_l2_scene` 同源docs/05 §4.14.3:
S_A 整case全驻留 / S_B 单batch可驻留全驻留**或单侧全驻留 + 对侧滑窗**)→
GM = V_in 一次r_in=1共享块重复读全部命中 L2S_C 双侧均超 L2 最小替换 2D 分组
L2 容量约束下最小 GM组间共享块落空回 GM组内窗口复用按 L2 计账
`r_in` = 重复读倍率GM 输入流量/输入总量r_in1下界 1 表示每字节只从 GM 读一次后续复用全命中 L2)。**分配策略的全部目标就是让 r_in 尽量接近 1**。
`r_in` = GM 输入流量/输入总量r_in1下界 1 表示每字节只从 GM 读一次后续复用
全命中 L2)。**分配策略的全部目标就是让 r_in 尽量接近 1**S_B 已识别"单侧可全驻留"
调度不再把可驻留 case 错误地按分组放大 GM只有双侧都放不下 L2 S_Cr_in > 1。
## 4. 核间分配策略B→M→N 线性映射
@@ -67,17 +81,19 @@ $$\text{BaseM}\times\text{BaseN} = \frac{L0C}{2\times 4B} = 32768\ \text{元素}
同一波 C 个核所需的 A 行块 + B 列块集合是"活跃工作集",超 L2 就回 GM 读。swizzle 编排输出块执行顺序,把每一波的活跃工作集压到最小。窗口宽度 `W = max{d | d|C, d ≤ ⌊√C⌋}`C=32 时 W=4窗口内先扫 M、扫满 W 行进下一列 N奇数窗口行 N 向反向(蛇形)。
**Step 5: L2 分组(工作集超 L2 时**
**Step 5: L2 场景判定与分组make_plan/evaluate 共用 `_l2_scene`issue#24/#32**
S_in = B(MK+KN)·dtS_out = B·MN·outB两个不变量GM 流量下界 = S_in + S_outL2 读入可用空间 L2_read = L2 S_out^resident
记单 batch 输入 a_b = MK·dt、b_b = KN·dt整 case V_in = S_in、V_out = S_out
A 行块 block_a = a_b/m_cnt、B 列块 block_b = b_b/n_cnt。
| 场景 | 条件 | 策略 |
| 场景 | 条件 | GM / L2 计账(每 batch |
|---|---|---|
| A 全驻留 | S_in + S_out L2 | 输入读一遍r_in=1输出驻留 L2 异步回写无需切分 |
| B 输入能驻留加输出超了 | S_in L2 < S_in+S_out | **输入驻留、输出直写 GM**保住 r_in=1校验总线 (S_in+S_out)/T_MMAD W_GM |
| C 输入本身超 | S_in > L2 | 分组执行,每组输入工作集 ≤ L2输出直写 GM |
| S_A 整case全驻留 | V_in + V_out ≤ L2 | GM = a_b+b_b重复读 (n_cnt1)a_b+(m_cnt1)b_b 走 L2输出驻留 L2GM 写=0 |
| S_B 单batch可驻留 | a_b+b_b ≤ L2**或**单侧全驻留+对侧滑窗b_b+2·block_a ≤ L2 或 a_b+2·block_b ≤ L2 | GM = a_b+b_br_in=1重复读 (n_cnt1)a_b+(m_cnt1)b_b 全部命中 L2输出直写 GM |
| S_C 双侧超 L2 | 以上均不满足 | 容量 m_grp·block_a+n_grp·block_b ≤ L2 下最小化 GM = ⌈n_cnt/n_grp⌉·a_b + ⌈m_cnt/m_grp⌉·b_b组间落空计 GM窗口 (n_cnt⌈n_cnt/n_grp⌉)a_b+(m_cnt⌈m_cnt/m_grp⌉)b_b 计 L2 |
场景 C 分组:每组覆盖 M 向 m_grp、N 向 n_grp 个基本块,`m_grp = ⌊D/(2·sM)⌋``n_grp = ⌊D/(2·sN)⌋`D = L2/(B·K·dt);重复读倍率 `r_in = (n_grp·M + m_grp·N)/(M+N)`。块内错位分核(对角线分配)避免同地址并发读串行化。
> 注:早期口径(预算 D = L2/(B·K·dt) 且对半切、组内窗口流量零计)已废弃
> issue#24 除总 B 的矛盾、issue#32 对半预算与窗口零计失真);分组不再对半、窗口复用如实计 L2。
**Step 6: 核内 tiling**BaseM×BaseN×4B×DB ≤ L0CBaseM×k_L0×dt×2 ≤ L0Ak_L0×BaseN×dt×2 ≤ L0B内轴按 dValue 256B/512B 对齐。