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:
@@ -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 惩罚}}$$
|
||||
|
||||
@@ -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 足够大时胜。
|
||||
|
||||
@@ -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/#32,GM 为读写共享总线):
|
||||
- `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.1/§4.3):
|
||||
S_A 整case全驻留 / S_B 单batch可驻留(全驻留**或单侧全驻留 + 对侧滑窗**)→
|
||||
GM = V_in 一次(r_in=1),共享块重复读全部命中 L2;S_C 双侧均超 L2 → 最小替换 2D 分组
|
||||
(整 L2 容量约束下最小 GM),组间共享块落空回 GM、组内窗口复用按 L2 计账。
|
||||
|
||||
`r_in` = 重复读倍率(GM 输入流量/输入总量),r_in≥1,下界 1 表示每字节只从 GM 读一次(后续复用全命中 L2)。**分配策略的全部目标就是让 r_in 尽量接近 1**。
|
||||
`r_in` = GM 输入流量/输入总量,r_in≥1,下界 1 表示每字节只从 GM 读一次(后续复用
|
||||
全命中 L2)。**分配策略的全部目标就是让 r_in 尽量接近 1**:S_B 已识别"单侧可全驻留"
|
||||
调度(不再把可驻留 case 错误地按分组放大 GM);只有双侧都放不下 L2 时(S_C)r_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)·dt,S_out = B·MN·outB。两个不变量:GM 流量下界 = S_in + S_out;L2 读入可用空间 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_cnt−1)a_b+(m_cnt−1)b_b 走 L2;输出驻留 L2(GM 写=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_b(r_in=1);重复读 (n_cnt−1)a_b+(m_cnt−1)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 ≤ L0C;BaseM×k_L0×dt×2 ≤ L0A;k_L0×BaseN×dt×2 ≤ L0B;内轴按 dValue 256B/512B 对齐。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user