diff --git a/BMM算子优化分析_Release/BMM算子优化分析_v0.94.md b/BMM算子优化分析_Release/BMM算子优化分析_v0.94.md index e27da74..19f9352 100644 --- a/BMM算子优化分析_Release/BMM算子优化分析_v0.94.md +++ b/BMM算子优化分析_Release/BMM算子优化分析_v0.94.md @@ -405,37 +405,42 @@ max 取更严格的 8192。修正后的归约阈值(θ_c≈12,grid_K=32 时 ### 实现方案 -**Step 0:singleCoreM / singleCoreN 的确定**(每核输出基本块尺寸) +**Step 0:SingleCoreM / SingleCoreN 的确定**(每核输出 tile 尺寸) -singleCoreM × singleCoreN 是 ASW_Basic 的基石参数——它决定了每核每次计算的输出 tile 大小,进而决定 mCnt/nCnt、swizzle 窗口、L2 执行组等所有后续参数。确定逻辑按约束链推导: +SingleCoreM × SingleCoreN 是每核每次处理的输出区域。**它不受 L0 容量直接约束**——L0 容量约束的是 BaseM/BaseN/BaseK(L0 级 tile,见 Step 5),SingleCoreM/N 在 BaseM/N 之上,一个 [SingleCoreM, SingleCoreN] tile 内部由多个 [BaseM, BaseN] L0 tile 组成。SingleCoreM/N 的核心影响是 **GM→L1 搬移效率和 L2 重复读率**: -*约束 1——L0C 容量*(输出 tile 必须放得下 L0C 双缓冲): +- SingleCoreM/N 越大 → 每次 GM→L1 搬移的数据量越大,dValue 越有保障,搬移效率越高;同时 L2 中同一份 A 行带/B 列带被更多核复用,重复读率越低 +- SingleCoreM/N 越小 → 总块数 mCnt×nCnt 越多,核间并行度越高,但单次搬移效率降低,L2 重复读率升高 + +*约束链*: + +**约束 1——并行度下限**:总块数须填满 C 核。 $$ -\text{singleCoreM} \times \text{singleCoreN} \times 4\text{B} \times 2 \le L0C \Rightarrow \text{singleCoreM} \times \text{singleCoreN} \le 32768 \text{ 元素} +mCnt \times nCnt \ge \Big\lceil \frac{C}{B} \Big\rceil \Rightarrow \frac{M}{\text{singleCoreM}} \times \frac{N}{\text{singleCoreN}} \ge \Big\lceil \frac{C}{B} \Big\rceil $$ -*约束 2——L0A/L0B 容量*(输入 tile 决定 baseK 上限): - -$$ -baseK \le \min\Big(\frac{L0A}{2 \cdot \text{singleCoreM} \cdot \text{dtype}},\; \frac{L0B}{2 \cdot \text{singleCoreN} \cdot \text{dtype}}\Big) -$$ - -*约束 3——dValue*:$baseK \cdot \text{dtype} \ge 256\text{B}$(BF16 为 128 元素)。 - -*约束 4——L1 容量*(双缓冲下驻留输入): +**约束 2——L1 容量**(双缓冲下驻留当前 tile 的输入): $$ 2 \cdot (\text{singleCoreM} + \text{singleCoreN}) \cdot k_{L1} \cdot \text{dtype} \le L1 $$ -*约束 5——搬移效率*:$\text{singleCoreM} \cdot K \cdot \text{dtype} \ge min\_TileSize$ 且 $K \cdot \text{singleCoreN} \cdot \text{dtype} \ge min\_TileSize$。 +其中 $k_{L1}$ 是 GM→L1 的 K 向粒度,须满足 dValue:$k_{L1} \cdot \text{dtype} \ge 256\text{B}$。 -*选取策略*:在约束 1 的上界(32768 元素)内,singleCoreM/singleCoreN 的长宽比应**跟随 M/N 的长宽比**——$\text{singleCoreM}/\text{singleCoreN} \approx M/N$,使 GM 访问的空间局部性最优(减少跨行/跨列的 strided 访问)。同时对齐到 16 的倍数(Cube 基本块粒度)。 +**约束 3——搬移效率**:单次 GM→L1 搬移量须达到 min_TileSize: -*例*:M=N=2048,方形 → singleCoreM=singleCoreN=$\lfloor\sqrt{32768}\rfloor_{16}$=176。约束 2:$baseK \le 16384/176 = 93$ → 取 80(16 对齐)。约束 3:$80 \times 2 = 160\text{B} \ge 128\text{B}$ ✓。 +$$ +\text{singleCoreM} \cdot k_{L1} \cdot \text{dtype} \ge min\_TileSize,\qquad k_{L1} \cdot \text{singleCoreN} \cdot \text{dtype} \ge min\_TileSize +$$ -*例*:M=4096、N=512,长条 → singleCoreM=256、singleCoreN=128($256 \times 128 = 32768$ 恰好满载 L0C/2)。约束 2:$baseK \le \min(16384/256, 16384/128) = \min(64, 128) = 64$。 +**选取策略**: + +在约束 1(并行度下限)和约束 2/3(搬移效率)之间取平衡。SingleCoreM/N 的长宽比应**跟随 M/N 的长宽比**($\text{singleCoreM}/\text{singleCoreN} \approx M/N$),使 GM 访问的空间局部性最优。对齐到 16 的倍数(Cube 基本块粒度)。 + +*例*(B=8、M=N=2048、K=1024、BF16):$\lceil C/B \rceil = 4$,需 $mCnt \times nCnt \ge 4$。取 $mCnt = nCnt = 2$ → singleCoreM = singleCoreN = 1024。约束 2:$k_{L1} \le 512\text{KB}/(2 \times 2048 \times 2\text{B}) = 64$ 元素 = 128B,恰好满足 dValue 下限。约束 3:$1024 \times 64 \times 2 = 128\text{KB} \ge 16\text{KB}$ ✓。 + +*例*(B=2、M=N=4096、K=512、BF16):$\lceil C/B \rceil = 16$,需 $mCnt \times nCnt \ge 16$。取 $mCnt = nCnt = 4$ → singleCoreM = singleCoreN = 1024。$k_{L1}$ 同上 = 64 元素。 **Step 1:mCnt / nCnt 与核间分配** @@ -445,42 +450,6 @@ $$ 总输出块数 = $B \times mCnt \times nCnt$,按 B→M→N 优先级分配到 C 核。 - -**核间组织**:先按 B/M/N 切出输出块,剩余核预算折成 K 向份数: - -$$ -blocksPerBatch = \Big\lfloor \frac{C}{B} \Big\rfloor,\qquad -grid_K = \frac{blocksPerBatch}{mCnt \cdot nCnt} -$$ - -mCnt、nCnt 收拢为 blocksPerBatch 的因子(避免碎核尾块);由条件 1 知 $mCnt \cdot nCnt \le blocksPerBatch/2$,故 $grid_K \ge 2$。归约组内核 c 负责 K 段 $[cK/grid_K,\; (c{+}1)K/grid_K)$。 - -**核内流水**:对自己的 K 段做标准分块流水(MTE2→L1→L0→mmad),段内多轮在 L0C 原地累加;段完部分和经 Fixpipe 写出。 - -**归约**: -* **workspace + AIV 归约(确定性)**:部分和写 workspace(每核 256×256×4B,另加 20MB 核间通信区),**workspace 优先驻留 L2**——归约读写走 5.2TB/s 的 L2 口而非 GM;AIV 从 L2 读回各段部分和、在 UB 内求和后写回(数据流 GM/L2→UB→AIV→UB→L2/GM,AIC:AIV=1:2); -* **AtomicAdd(非确定性)**:部分和直接原子累加到输出 GM,省一遍读回;确定性等级 >1 禁用。 - -**参数搜索**:$grid_K$ 从 2 起按 2 的幂递增,取同时满足条件 2/3 的最小值;都不满足则退为降核 ASW_Basic。 - ---- - -## 八、ASW_Basic 分支 - -### 进入分支条件(汇总) - -1. $P = \dfrac{B \cdot MN \cdot 4\text{B}}{L0C} \ge C$ -2. 无 batch 结构限制(BatchA=BatchB、交叉广播均可);典型进入路径:$B < C$(切 B 买不满核),或 $B \ge C$ 但 IterBatch/MergeBatch 条件不满足时的兜底 -3. **降核模式**:$P < C$ 且不满足 StreamK 进入条件 → 只用 $\lceil P \rceil$ 个核,其余核闲置 - -### 逐条解释 - -1. **并行度补齐**:以 L0C 满载为基本块粒度,B×M×N 能切出至少 C 个独立输出块,则切 M/N(或混合切)并行度够用。切 M/N 的固有代价是共享矩阵被多核重复读,但共享部分驻留 128MB L2 时重复读以 5.2TB/s 命中 L2 而非 1.6TB/s 的 GM,代价大部分被吸收。 -2. **兜底性质**:ASW_Basic 是实践中最常命中的分支——B 可大可小可等 1,交叉广播也由此承接(对广播侧做 L1/L2 驻留,共享关系与切 M/N 同构)。 -3. **降核模式**:P < C 且 K 也不够格走 StreamK 时,并行度凑不满核。此时与其强行把 M/N 切得更碎(tile 跌破 min_TileSize、dValue 跌破 128B,搬移效率崩塌,反而更慢),不如**只用 ⌈P⌉ 个核**、每核承担一个完整输出块(L0C 满载粒度),其余核闲置。这类 case 的时延绝对值小,继续切分引入的调度与搬移效率损失大于并行收益——降核是理性选择而非偷懒。 - -### 实现方案 - **Step 2:核间切分维度选择(按共享代价从低到高)**:切 B(零共享,先试)→ 切 M(右矩阵 $KN\cdot\text{dtype} \le L2$ 则驻留 L2)→ 切 N(对称)→ 混合切(靠 swizzle + L2 切分管理)→ 降核(见 Step 7)。 **Step 3:swizzle——ASW 滑窗蛇形** @@ -617,11 +586,11 @@ $$ 补充:若输出会被后续算子立即消费(融合场景),输出驻留 L2 让下游读命中,场景 B/C 的策略反过来;本文按单算子边界分析。 -**Step 5:核内 tiling**:$\text{singleCoreM} \times \text{singleCoreN} \times 4\text{B} \times DB \le L0C$;$\text{singleCoreM} \times k_{L0} \times \text{dtype} \times 2 \le L0A$、$k_{L0} \times \text{singleCoreN} \times \text{dtype} \times 2 \le L0B$;内轴按 dValue 256B/512B 对齐;L1 按容量开双缓冲,余量充足开 4 buffer。 +**Step 5:核内 tiling**(BaseM/BaseN/BaseK——L0 级 tile,受 L0 容量直接约束):$\text{BaseM} \times \text{BaseN} \times 4\text{B} \times DB \le L0C$;$\text{BaseM} \times k_{L0} \times \text{dtype} \times 2 \le L0A$、$k_{L0} \times \text{BaseN} \times \text{dtype} \times 2 \le L0B$;内轴按 dValue 256B/512B 对齐。SingleCoreM/N 内部按 BaseM/BaseN 进一步切分为 L0 tile 逐个计算。L1 按容量开双缓冲,余量充足开 4 buffer。 **Step 6:内部特化(参数极限,不是独立分支)**:单边无 batch 且该侧矩阵小($M \le 256$、$MK\cdot\text{dtype}\cdot 2 \le L1$、对侧每核循环 ≥4 轮)时小侧整个常驻 L1、只搬一次(L1 全载)。 -**Step 7:降核模式实现**:tiling 时 `usedCoreNum = ⌈P⌉`(不强制 C),基本块在 L0C 容量内取最大($M^t N^t \cdot 4\text{B} \le L0C$),每核按标准核内流水(L1→L0→Cube→L0C→Fixpipe)处理自己的输出块;核间无共享无依赖,无需 swizzle 与 L2 切分。降核后 GM 并发搬移核数若 < minCoreNum,带宽利用率上限被压低——这正是降核区 case 时延的瓶颈所在,也是"时延绝对值小、不再继续优化"的定量注脚。 +**Step 7:降核模式实现**:tiling 时 `usedCoreNum = ⌈P⌉`(不强制 C),SingleCoreM/N 在 L0C 容量内取最大($\text{singleCoreM} \times \text{singleCoreN} \times 4\text{B} \le L0C$),每核按标准核内流水(L1→L0→Cube→L0C→Fixpipe)处理自己的输出块;核间无共享无依赖,无需 swizzle 与 L2 切分。降核后 GM 并发搬移核数若 < minCoreNum,带宽利用率上限被压低——这正是降核区 case 时延的瓶颈所在,也是"时延绝对值小、不再继续优化"的定量注脚。 ---