From 45e0acc75531123feded9dce0eb515d6e08126c4 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 27 Aug 2026 11:22:23 +0000 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=20BatchMatmul=E7=AE=97?= =?UTF-8?q?=E5=AD=90=E7=89=B9=E6=80=A7=E5=88=86=E6=9E=90.html=20=E5=88=B0?= =?UTF-8?q?=20BMM/=20=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BMM/BatchMatmul算子特性分析.html | 754 +++++++++++++++++++++++++++++++ 1 file changed, 754 insertions(+) create mode 100644 BMM/BatchMatmul算子特性分析.html diff --git a/BMM/BatchMatmul算子特性分析.html b/BMM/BatchMatmul算子特性分析.html new file mode 100644 index 0000000..88fe6d2 --- /dev/null +++ b/BMM/BatchMatmul算子特性分析.html @@ -0,0 +1,754 @@ + + + + + +Batch Matmul 算子特性分析 + + + + + +
+

Batch Matmul 算子特性分析

+
+

版本:v1.0 | 目标芯片:DV100(与昇腾 950PR / DAV_3510 同档:32 AIC / 64 AIV,GM 1.6TB/s,L2 128MB / 5.2TB/s) +本文目标:任意 shape/dtype/layout 的 BMM case,都能系统地推导出其在 NPU 上的最优软件实现方案(端到端总时延最短),并论证分支体系的完备性与极小性。 +阅读主线:第 1 章定义问题 → 第 2 章定义"最优" → 第 3 章推导分支划分 → 第 4 章逐分支给出进入条件与实现方案 → 第 5 章决策流程 → 第 6 章完备性审视(漏洞检查)。

+
+
+

1. 算子功能与接口

+

1.1 算子功能

+

Batch Matmul(BMM)完成带 batch 维的矩阵乘计算:对 batch 维的每个索引独立执行一次矩阵乘,再加可选偏置:

+

$$ +C[b, m, n] = \sum_{k=0}^{K-1} A[b, m, k] \cdot B[b, k, n] + bias[b, 1, n] +$$

+

C = A @ B + bias。A、B 输入维度典型为 3 维(支持最多 4 级 batch 维 $b = b_0 b_1 b_2 b_3$ 展平),最后两维做矩阵乘。

+

1.2 接口参数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数形状数据类型layout说明
左矩阵 A[BatchA, M, K]dtype(FP16/BF16/FP8/…)典型 ND可带转置标记(isATrans)
右矩阵 B[BatchB, K, N]dtype典型 ND可带转置标记(isBTrans),推理场景可为 weightNz
偏置 bias[B, 1, N]dtype固定 ND可为空
输出 C[BatchC, M, N]dtype(可随路量化)典型 NDBatchC = broadcast(BatchA, BatchB)
+

广播语义:batch 维兼容广播——每一级 batch 维上,两侧取值要么相等、要么为 1;输出该维取两者的最大值。注意两类广播的形态差异:

+ +

1.3 case 空间:决定实现方式的特征量

+

一个 BMM case 的实现方式完全由以下特征量决定:

+

$$ +(\; B,\; M,\; N,\; K,\; \text{dtype},\; \text{layout/转置},\; \text{广播形态} \;) +$$

+

其中 $B$ = BatchC(展平后的输出 batch 数)。后续全部分析就是回答:给定这组特征量,最优实现是什么。

+
+

2. 性能模型:什么叫"最优"

+

2.1 总时延 = 流水线最慢的一级

+

NPU 上 BMM 的执行是核内多级硬件流水的并行——Cube 计算(MMAD)、GM/L2→L1 搬移(MTE2)、L1→L0 搬移(MTE1)、L0C 写出(Fixpipe),多核并行时各流水级时延可被双缓冲(double buffer)等机制相互掩盖,最终:

+

$$ +\boxed{\;T_{total} = \max\big(T_{MMAD},\; T_{MTE2},\; T_{MTE1},\; T_{Fixpipe}\;[,\;T_{Reduce}]\big)\;} +$$

+

算子优化的关键就是对瓶颈流水级的优化。 由此直接得出一个重要的设计自由度——瓶颈交换

+
+

当 MTE2(搬移)是瓶颈、MMAD(计算)不是瓶颈时,可以牺牲一定 MMAD 时延(例如冗余计算)换取 MTE2 性能提升;反之,当 MMAD 是瓶颈时,可以牺牲一定 MTE2 时延(例如重复搬移)换取计算效率提升。只要瓶颈级时延下降,总时延就下降。

+
+

后文会看到:MergeBatch 就是"牺牲算力换搬移效率"的典型,ASW_Basic 切 M/N 就是"牺牲搬移(重复读)换并行度"的典型——它们的存在正当性都来自这个 max 模型。

+

2.2 目标芯片关键规格与经验常数

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
规格项数值对设计的意义
AIC / AIV 核数32 / 64(1:2)核间并行度上限 $C = 32$;StreamK 归约可用 AIV
Cube 算力 FP16/BF16≈486 TFLOPS(单核 ≈ 16×16×16 MAC/拍)算存比分子
GM 带宽1.6 TB/s(读写共享总线)访存 Bound 的分母;读+写互相挤占
L2 Cache128MB,5.2 TB/s(读写各独享)重复读取的吸收层;Cube 输出写 L2 即算完成
L1 / L0A / L0B / L0C512KB / 64KB / 64KB / 256KB(每 AIC)核内分块的容量约束;L0C 按 FP32 累加计
UB512KB(每 AIV)向量通路/归约
+

GM→L1 搬移效率(ND2NZ)达到 90%+ 带宽利用率的四条经验约束(DV100 实测,重要性递减):

+
    +
  1. 参与核数:建议 32 核并行搬移,至少 3/4 核(24 核)并发——核数不足时带宽利用率上限被压低;
  2. +
  3. 单核搬移数据总量 ≥ 480KB(min_DatamountPerCore);
  4. +
  5. 单次搬移 tile 大小 ≥ 16KB(min_TileSize);
  6. +
  7. dValue(单次搬移的连续内轴字节数,如非转置 A 的 K 向、非转置 B 的 N 向)≥ 128B,建议 256B,最好 512B。
  8. +
+
+

这些常数(480KB、16KB、256B/512B,以及后文的 $b_{thr}=4$、$k_{thr}$=32B/dtype、$minCoreNum \approx 0.8 \times 32$)都是该档芯片的实测经验值;换芯片时本文的所有逻辑结构不变,只需替换常数表。

+
+

2.3 算存比与 Bound 判定

+

约定:以"元素"为访存单位(1 元素 = dtype 字节),算存比单位为 FLOP/元素。

+ +

$$ +AI = \frac{2MNK}{(MK + KN)} = \frac{2MN}{M + N} \quad [\text{FLOP/元素}] +$$

+ +

$$ +AI_{full} = \frac{2MNK}{MK + KN + MN} \quad [\text{FLOP/元素}] +$$

+ +

$$ +R = \frac{\text{Cube 峰值算力}}{\text{GM 带宽} / \text{dtype 字节}} = \frac{486 \times 2}{1.6} \approx 607.5 \quad [\text{FLOP/元素,BF16/FP16}] +$$

+

判定规则:$AI < R$ → 访存 Bound(瓶颈在 MTE2,优化重心是搬移效率与复用);$AI > R$ → 计算 Bound(瓶颈在 MMAD,优化重心是 Cube 利用率与流水掩盖)。注意一个有用的事实:低位宽 dtype(FP8、MXFP4)算力同倍数翻倍而元素字节同倍数减半,$R$ 近似不变,因此该平衡点对该芯片各低位宽 dtype 通用。

+

大白话:矩阵乘就像搬砖盖楼——Cube 是起重机(算力),GM 带宽是供货卡车(带宽)。算存比就是"每块砖要盖多少平米"。每块砖盖的平米数低于起重机的额定配比时,楼永远盖不快,问题出在供货而不在起重机——这时候优化要围绕"怎么少堵车、怎么一次多运点",而不是换更大的起重机。

+
+

3. 分支划分的系统推导

+

本章是全文逻辑主线:从分块计算的本质出发,不靠经验罗列,推导出五大分支的划分。

+

3.1 分块计算的本质与四个可切维度

+

BMM 在 NPU 上实现的本质是:把参与计算的数据分块(tile),由 32 个 AIC 核并行 + 串行地完成这些分块的计算,再组合成最终结果:

+

$$ +C[B, M, N] = \sum_{\kappa} A[B, M, K_\kappa] @ B[B, K_\kappa, N] +$$

+

分块有 4 个维度:B、M、N、K核间怎么分这 4 个维度,就是分支划分的第一性问题(核内分块是第二性问题,属于各分支内部的 tiling)。

+

3.2 四个维度的切分特征:一张决定性的表

+

从"读入 / 计算 / 写出"三个视角考察每个维度的核间切分特征(这是后续一切推导的基石):

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
切分维度读入特征计算特征写出特征
切 B每个数据块只被固定的 1 个核读取,核间零重复读每个输出块由 1 个核独立完成,无核间依赖只写最终结果,无中间结果
切 M / 切 N切 M 则同一右矩阵块被多核重复读;切 N 则同一左矩阵块被多核重复读每个输出块由 1 个核独立完成,无核间依赖只写最终结果,无中间结果
切 K每个数据块只被固定的 1 个核读取,零重复读每个输出块由多核共同完成,存在核间依赖有中间结果写出,需核间 Reduce 归约
+

为什么特征差异这么大?两条硬件层面的根本原因:

+ +

3.3 完备枚举:15 种核间切分组合

+

4 个维度的任意非空子集都可作为一种核间切分方案,共 $2^4 - 1 = 15$ 种:

+

$$ +\{B\},\{M\},\{N\},\{K\},\{B,M\},\{B,K\},\{B,N\},\{M,K\},\{M,N\},\{K,N\},\{B,M,K\},\{B,M,N\},\{B,K,N\},\{M,K,N\},\{B,M,K,N\} +$$

+

任何实现方案必属于其中一种 ⇒ 这 15 种是完备的。按 §3.2 的特征分组:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
组合共同特征优化重心
纯 B{B}零重复读,读写数据量固定访存 Bound:搬移效率高;计算 Bound:计算效率高
含 M/N 不含 K{M},{N},{M,N},{B,M},{B,N},{B,M,N}可能有重复读访存 Bound:重复读尽量少 + 搬移效率高;计算 Bound:计算效率高
含 K{K},{B,K},{M,K},{K,N},{B,M,K},{B,K,N},{M,K,N},{B,M,K,N}有中间结果写出 + 归约计算效率高,且归约引入的额外 MTE2/Fixpipe 时延不能成为新瓶颈
+

3.4 代价不对称性:切分维度的"价格表"

+

15 种组合的代价结构只由两个布尔特征决定——是否含 K、是否含 M/N。三个维度的"核间切分价格"严格排序:

+

$$ +\text{cost}(\text{切}B) = 0 \;<\; \text{cost}(\text{切}M/N) \;\ll\; \text{cost}(\text{切}K) +$$

+ +

"价格表"不是经验,是 BMM 语义 + L0C 累加机制 + L2/GM 带宽结构三条事实的推论。 整条分支决策树就是一句话:按价格从低到高购买并行度,买不够才加价。

+

3.5 推导主链:从价格表到五大分支

+

第 0 层:问题归约(能降维就不在 BMM 本体里解决)。

+ +

第 1 层:归约不掉的 case(BatchA = BatchB = B > 1,K ≥ 2),必须在 BMM 框架内组织 4 维分块。先买免费的 B 维。

+ +

第 2 层:免费的 B 买不满 32 核,加价买廉价的 M/N。

+ +

第 3 层:廉价维度也买不满,才买昂贵的 K。

+ +
case (B, M, N, K, dtype, layout, 广播形态)
+   │
+   ▼
+[0] K=0? → AIV 清零;K=1? → AIV 逐元素乘        ← 前置通路层(正交于切分)
+   │ K ≥ 2
+   ▼
+[1] BatchA=1 或 BatchB=1? ──是──→ 转Matmul(问题归约,复用 Matmul 体系)
+   │ 否(BatchA=BatchB=B>1,或交叉广播)
+   ▼
+[2] 并行度账本:P = B·⌈M/16⌉·⌈N/16⌉ 与 C=32 比较
+   │
+   ├─ B ≥ 32(切 B 可满核)─────────────────────────┐
+   │    M×N 大,Cube 饱 → IterBatch                 │
+   │    M×N 小,Cube 饿,且访存 Bound → MergeBatch  │
+   │                                                │
+   ├─ B < 32 且 P ≥ 32 → ASW_Basic(切 M/N 补并行,  │
+   │                     共享读取由 L2+swizzle 吸收) │
+   │                                                │
+   └─ P < 32(B/M/N 用尽仍缺并行,K 大)→ StreamK    │
+      (切 K 买并行,付归约代价)◀──────────────────┘
+
+

3.6 完备性与极小性:五大分支不多不少

+

完备性。对归约不掉的 case,15 种组合按"(是否含 K,是否含 M/N)"坍缩:

+ +

$1 + 1 + 2 = 4$,加上第 0 层的归约分支(转Matmul)= 5。任何合法 case 必落其一,无空洞。

+

极小性。每个分支都有它"唯一最优"的 shape 区域,去掉任何一个都会有 case 失去最优实现:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
分支独占最优的代表 case(BF16)替代方案为何更差
转MatmulBatchB=1, B=128, M=N=K=2048免费折叠后 Matmul 体系的 L2 切分/全载直接可用;BMM 分支内重做一遍无收益
IterBatchB=32, M=N=K=4096ASW 切 M/N 引入无谓共享读;MergeBatch 引入无谓冗余算力
MergeBatchB=128, M=32, N=128, K=64IterBatch 的 L0C 利用率仅 ~1.6%,Cube 空转,搬移 tile 碎(<16KB)带宽利用率崩
ASW_BasicB=2, M=N=8192, K=1024切 B 仅 2 核干活;StreamK 付无谓归约
StreamKB=1, M=N=64, K=65536不切 K 时 P=16 < 32,近半核闲置,时延差数量级
+

⇒ 五大分支构成极小完备集

+

3.7 大白话总结

+
+

把 BMM 想成给 32 个工人分一批"矩阵乘订单":

+
    +
  • 能整单外包的就别自己干:一侧只有一个 batch,问题其实就是一次普通矩阵乘,直接交给成熟的 Matmul 产线(转Matmul);
  • +
  • 按订单分(切 B)最省心:每人几单,互不干扰(零重复搬料、零协调)。订单多时,单大就一单接一单干(IterBatch);单太小时一人同时干几单、拼成大活干,虽然多做了点无用功,反正瓶颈在等料不在干活(MergeBatch);
  • +
  • 订单不够分,就按行/列拆单(切 M/N):大家会重复领同一份料,但料放在近处仓库(L2),多跑几趟近仓库很便宜(ASW_Basic);
  • +
  • 行/列也不够拆,只好沿深度 K 拆:几个人合做同一块输出,各算一段再汇总——汇总是要额外开会的(Reduce),所以只在实在分不满、且 K 足够长时才这么干(StreamK)。
  • +
+
+
+

4. 各分支详解:进入条件与实现方案

+
+

每节按统一结构展开:做什么(定义)→ 什么时候进(进入条件逐条 + 每条的理由)→ 怎么做(实现方案与参数求解)→ 与源码对照(批判性)

+
+

4.0 前置通路层:K 退化 case

+

在切分决策之前先做计算通路判断:

+ +

这一层与"切分维度"正交:五大分支管理的都是 Cube 通路上的 case(K ≥ 2)。K 极小(如 K < 16,不足一个 fractal)时同理应优先考虑向量通路或尾部补齐。

+

4.1 转Matmul(问题归约分支)

+

做什么:当 BatchA = 1BatchB = 1 时,把 batch 维折叠进矩阵维度,转化为普通 Matmul,计算完成后按需恢复 batch 维。

+

为什么这么做:单边 batch=1 的 BMM 与普通 Matmul 在数学上只差一个维度标签。Matmul 的优化体系(L2 切分、AL1/BL1 全载、swizzle)比 BMM 各分支在"单样本"情形下更成熟——站在巨人肩膀上,不重复造轮子。BMM 本体只研究相对 Matmul 有差异化的 case(双侧 batch > 1)。

+

折叠规则与代价(关键的不对称性)

+ + + + + + + + + + + + + + + + + + + + +
情形折叠方式是否免费
BatchB = 1左矩阵 [B, M, K] 的 batch 维与 M 维在 ND 布局下内存相邻,直接视图为 [B·M, K];输出 [B·M, N][B, M, N] 的内存布局逐元素一致完全免费:零输入重排、零输出 split
BatchA = 1需将右矩阵 [B, K, N] 折叠为 [K, B·N]有代价:B 的 batch 维与 N 维在内存中不相邻(中间隔 K),折叠等价于一次 [B,K,N]→[K,B,N] 的转置重排(O(B·K·N) 读写),且输出 [M, B·N] 与目标 [B, M, N] 之间存在置换,需要随路 scatter
+
+

这一不对称性是对"直接折叠"设想的必要修正(详见 6.2)。BatchB = 1 无脑走转Matmul;BatchA = 1 需比较"重排一次 B + Matmul 收益"与"广播友好的 IterBatch/ASW_Basic(A 驻留 L2/L1 天然共享,不重排任何数据)"——大 case 重排代价被摊薄,走转Matmul;小 case 直接走 BMM 分支。源码中的 MergeBatchAndMAxis() 只做了 batchB=1 方向的折叠,与"该方向免费"的判断互为印证。

+
+

进入条件BatchA = 1 || BatchB = 1。其中 BatchB = 1 恒进;BatchA = 1 时按上述代价比较决定(决策规则见第 5 章)。

+

BatchA = BatchB = 1:纯 Matmul,是转Matmul 的特例。

+

4.2 MergeBatch(多 batch 合并计算)

+

4.2.1 做什么

+

核间按 B 分核(每核负责 $b_{core}$ 个 batch),核间无同步无通信。核内将多个 batch 合并计算

+

$$ +[b, M, K] @ [b, K, N] \;\Rightarrow\; [bM, K] @ [K, bN] = [bM, bN] \;\xrightarrow{\text{BlockTrace}}\; [b, M, N] +$$

+

其中 BlockTrace 指以 $[M, N]$ 的 block 粒度取结果矩阵的块对角线作为各 batch 的有效输出:$C[i, m, n] = R[iM + m,; iN + n]$。交叉项(第 i 个 batch 的 A 乘第 j≠i 个 batch 的 B)被算出但丢弃——这就是"算力浪费",浪费比例 $(b-1)/b$。

+

为什么允许浪费:进入该分支的 case 必然是访存 Bound(条件三保证),瓶颈在 MTE2 不在 MMAD,浪费的算力被搬移时延掩盖(§2.1 瓶颈交换)——用本来闲置的 Cube 算力,换 tile 变大后的搬移效率与 Cube 利用率

+

4.2.2 进入条件(逐条 + 理由)

+

设计原则四条:① 硬件时延可流水掩盖(double buffer 乒乓);② 满足容量约束(每次计算 L1/L0A/L0B/L0C 放得下);③ GM→L1 搬移高效(§2.2 四条经验约束);④ 算力有浪费但计算不能成为瓶颈。

+

形式化后,进入 MergeBatch 需同时满足:

+

条件 1(batch 够分且够合并)BatchA = BatchB(无广播)且

+

$$ +b_{core} = B / aicNum \ge b_{thr} +$$

+

$b_{thr}$ 是"多 batch 合并搬移能拿到效率收益"的最小合并数——$b$ 太小时合并的搬移收益抵不过实现复杂度,不如 IterBatch 且完全不浪费算力(功耗)。DV100 实测经验值 $b_{thr} = 4$。

+

条件 2(合并数 b 的上下界):设核内单次 Cube 计算合并 $b$ 个 batch($b \le b_{core}$),要求 $b \ge b_{thr}$ 且 $b$ 由以下约束共同封顶:

+ +

$$ +AI(b) < R \;\Longleftrightarrow\; b < b_{AI} = \frac{R \cdot (M + N)}{2MN} +$$

+ +

$$ +2 \cdot (bM)(bN) \cdot 4\text{B} \le 256\text{KB} \;\Rightarrow\; b \le b_{L0C} +$$

+ +
+

乒乓取舍:若 $b_{core}$ 小于"不乒乓时 L0C 允许的合并数上限",说明 batch 余量不足,只能不乒乓(牺牲流水掩盖换合并数);否则乒乓。形式上 $b_{max} = \min(b_{AI}, b_{L0C}^{(\text{是否乒乓})}, b_{core})$。

+
+

条件 3(访存 Bound 性质)

+

$$ +\frac{2MN}{M + N} < \frac{R}{b} +$$

+

即 case 固有算存比显著低于平衡点(低一个合并倍数 $b$ 的量级)——这是"浪费可被掩盖"的定量保证,也是条件 2 中 $b_{AI} > b$ 的另一写法。

+

条件 4(K 向搬移效率):L1 级 K 切分 $k_{L1} = K / StepK$(StepK 为正整数),要求 $k_{L1} \ge k_{thr}$,DV100 下 $k_{thr} = 32\text{B}/\text{dtype}$(BF16 即 16 元素)。理由:$k_{L1}$ 决定 ND2NZ 的 dValue,过碎则搬移指令效率崩(§2.2 第 4 条)。

+

条件 5(L1 驻留与 tile 效率):L1 级 batch 驻留数

+

$$ +b_{L1} = \frac{L1_{size}}{(M k_{L1} + k_{L1} N) \cdot \text{dtype}}, \qquad b_{L1} > b +$$

+

(L1 驻留的 batch 组必须大于单次计算的合并数,否则合并无从谈起),且搬移 tile 大小满足效率:左矩阵非转置时 $\max(b_{L1} M k_{L1} \cdot \text{dtype},; k_{L1} N \cdot \text{dtype}) > min_TileSize$(16KB);左矩阵转置时相应调整。

+

条件 6(单核搬移总量)

+

$$ +b_{core} \cdot (M k_{L1} + k_{L1} N) \cdot \text{dtype} \ge min\_DatamountPerCore = 480\text{KB} +$$

+

对应 §2.2 第 2 条:单核搬移数据总量不足时带宽利用率上限被压低。

+

条件汇总逻辑:条件 1 定资格(batch 够多),条件 2/3 定上限(别算出瓶颈、别撑爆 L0),条件 4/5/6 定下限(搬移效率不能崩)。上限与下限之间必须有交集,交集为空则该 case 与 MergeBatch 无缘。

+

4.2.3 核内 b 与 baseK 的取值优化

+

进入分支后,$b$ 与 baseK 的具体取值有一个重要性质:在访存 Bound 前提下,$b < b_{AI}$ 时 b 的取值不影响性能,baseK 只需满足分形约束(16 倍数)也不影响算存比——因为瓶颈是搬移,算力余量内怎么切都一样。据此:

+
    +
  1. 先由条件 2 求 $b_{max}$,实际 $b$ 在 $[b_{thr}, b_{max}]$ 内取,且尽量均匀($b_{core}$ 整除 $b$)——每次计算的 $b$ 均匀一致对功耗更有利;
  2. +
  3. 再由 $b$ 反查 L0AB 允许的最大 baseK:$baseK_{max} = \min\left(\dfrac{64\text{KB}}{2 \cdot bM \cdot \text{dtype}},; \dfrac{64\text{KB}}{2 \cdot bN \cdot \text{dtype}},; \dfrac{C0_{size}}{\text{dtype}}\right)$,向下取 16 倍数。
  4. +
+

4.2.4 数值例子(把条件过一遍)

+

case:B=128, M=32, K=64, N=128, BF16,32 核。

+
    +
  1. 资格:$b_{core} = 128/32 = 4 \ge b_{thr} = 4$ ✓;
  2. +
  3. 算存比:$AI = 2 \times 32 \times 128 / (32 + 128) = 51.2$ FLOP/元素 $< R = 607.5$ ✓ 访存 Bound;$b_{AI} = 607.5 / 51.2 \approx 11.86$,即 $b \le 11$ 都不会进入算力 Bound——算存比约束很宽;
  4. +
  5. L0C 约束(乒乓):$2(b \cdot 32)(b \cdot 128) \times 4\text{B} \le 256\text{KB} \Rightarrow b^2 \le 8 \Rightarrow b \le 2$(不乒乓则 $b \le 4$)——L0C 才是真正的紧约束
  6. +
  7. 取 b = 2(= $b_{core}$ 的因子,均匀):L0B 给出 $k_{L0} \le 64\text{KB} / (2 \times 2 \times 128 \times 2\text{B}) = 64$,$K = 64$ 一步到位,baseK = 64;
  8. +
  9. 搬移效率:$k_{L1} = 64 \ge k_{thr} = 16$ ✓;单核搬移量 $4 \times (32 \times 64 + 64 \times 128) \times 2\text{B} = 80\text{KB}$ —— 不足 480KB,条件 6 不满足!
  10. +
+

结论:该 case 在"单核搬移总量"一项上不达标——这正是 MergeBatch 条件体系的用处:它提前告诉你瓶颈不在算力而在搬移效率,此 case 应尝试合并更多 K/提高 $b_{core}$ 数据量,或由时延模型与 IterBatch/ASW_Basic 比较后定夺。

+

4.2.5 执行流程

+
核间:32 核,每核 b_core 个 batch
+核内(每核):
+  for k_l1 in range(0, K, kL1):                    # L1 级 K 切分
+    MTE2: A[bL1组, M, k_l1:k_l1+kL1]、B[bL1组, k_l1:k_l1+kL1, N] → L1(乒乓)
+    for b_start in range(0, bL1, b):               # 按合并数 b 分组
+      for k_l0 in range(0, kL1, kL0):              # L0 级 K 切分
+        MTE1: A[bM, kL0] → L0A;B[kL0, bN] → L0B
+        Cube: [bM, kL0] @ [kL0, bN] → L0C 累加
+      Fixpipe: BlockTrace 取 b 个 [M, N] 对角块 → L2/GM
+
+

4.2.6 与源码对照(批判性)

+

源码 batch_matmul_v3_mergebatch_basicapi_tiling.cpp 的 IsCapable 条件:各级 batchA_i == batchB_i、batchC ≥ 4 × aicNumalignK ≥ 64M ≤ N、无 bias、非 NZ、拒绝非连续转置等。对照分析:

+ +

4.3 IterBatch(逐 batch 计算)

+

4.3.1 做什么

+

核间按 B 分核(每核 1 个或多个 batch),核间无同步无通信;核内逐个 batch 分别执行标准 Matmul 分块(L1→L0A/L0B→Cube→L0C→Fixpipe)并输出。无算力浪费、无跨 batch 依赖——是"切 B"最朴素的形态。

+

4.3.2 进入条件(三大类 + 理由)

+

满足以下任一

+

类 1(计算 Bound 型)

+

$$ +AI_{full} = \frac{2MKN}{MK + KN + MN} \ge R \quad \text{且} \quad BatchA = BatchB,\; b_{core} = B / aicNum \in \mathbb{Z}^+ +$$

+

理由:连输出写出都计入仍是计算 Bound,则瓶颈恒在 Cube——只要负载均衡($b_{core}$ 整除,各核同量),逐 batch 计算就是满算力实现,无需任何花哨。

+

类 2(输出驻留 L2 的均衡型)

+

$$ +\frac{2MN}{M+N} \ge R_{读GM} \;\;\text{且}\;\; 2K \ge R_{写L2} \;\;\text{且}\;\; MN \cdot \text{dtype} \le L2_{size} \;\;\text{且}\;\; BatchA = BatchB,\; b_{core} \in \mathbb{Z}^+ +$$

+

理由:读侧访存不弱($AI \ge R_{读GM}$);单 batch 输出 $MN \cdot \text{dtype} \le 128$MB 可驻留 L2——Cube 输出写 L2 即算完成,写 GM 的流量被省掉;$2K$ 是"每写出一个元素对应的计算量",$2K \ge R_{写L2}$ 保证写 L2 的 5.2TB/s 也不是瓶颈。三个条件合起来 = 读、算、写三条路都不堵

+

类 3(访存 Bound 型):$\dfrac{2MN}{M+N} < R$ 且同时满足:

+
    +
  1. $BatchA = BatchB$ 且 $b_{core} = B / aicNum \ge 1$;
  2. +
  3. 负载均衡:访存 Bound 时核负载利用率建议 bAvg/bMax > 0.8(计算 Bound 时建议 100%)。操作化表述:B 整除核数,或尾波(B mod aicNum)活跃的核数 ≥ minCoreNum(DV100 取 0.8 × 32 ≈ 26)。注意:若只写 B mod aicNum > minCoreNum 会误杀整除 case(余数 0 恰恰是完全均衡),判据应以均衡比为准、余数规则为其近似
  4. +
  5. 单核搬移不重复读(访存 Bound 下重复读就是纯损失),按 L1 容量分五种形态之一: +
      +
    • (a) $b_{core} = 1$ 且 $(MK + KN) \cdot \text{dtype} \le L1_{size}$:单 batch 左右矩阵同时驻留 L1,零重复读;
    • +
    • (b) $b_{core} > 1$ 且 $2(MK + KN) \cdot \text{dtype} \le L1_{size}$:L1 放下 2 个 batch 形成乒乓流水;
    • +
    • (c) 放不下的,$(MK + KN/Step) \cdot \text{dtype} \le L1_{size}$(或 M/Step 对称):一矩阵不切、另一切分,分块大小仍须 > min_TileSize;
    • +
    • (d) $b_{core} > 1$ 时上一条的半容量版本(L1 双 batch 乒乓预算减半);
    • +
    • (e) 左右都切 K:$(M \cdot K/Step + K/Step \cdot N) \cdot \text{dtype} \le L1_{size}$;
    • +
    • 以上 (c)(d)(e) 切分后的分块均须满足搬移效率(tile ≥ 16KB、dValue ≥ 128B/256B)。
    • +
    +
  6. +
+

4.3.3 设计原理(为什么是这些条件)

+
    +
  1. 核间切 B 零共享零依赖,唯一的系统性风险是负载不均——所以均衡是第一条件;
  2. +
  3. 输出须满足 L0C 容量:$MN \cdot 4\text{B} \le L0C$(否则核内还要切 M/N,那就不是纯 IterBatch 而是 ASW 行为——但注意 IterBatch 核内允许对单 batch 做标准 M/N/K tiling,此处的准确含义是"核内 tiling 不构成跨 batch 的耦合");
  4. +
  5. 访存 Bound 时单核数据不得重复读——L1 装得下才不重复,装不下就按 Step 切分且切分后仍满足搬移效率下限;
  6. +
  7. 与 MergeBatch 的分工:IterBatch 不浪费算力,但需要"单 batch 足够大"撑搬移效率与 Cube 利用率;MergeBatch 用浪费换效率,专治小 M×N。两者在 $M \times N$ 的中段重叠,由时延模型仲裁(第 5 章)。
  8. +
+

4.3.4 执行流程

+
核间:32 核分 batch(尽量整除,尾波核数 ≥ minCoreNum)
+核内(每核):
+  for batch in 本核的 b_core 个 batch:           # 逐个 batch
+    for m_tile / n_tile(核内标准 tiling):
+      for k_tile in range(0, K, baseK):
+        MTE2 预取下一 k_tile → L1(双缓冲)
+        MTE1: L1 → L0A/L0B
+        Cube: mmad → L0C 原地累加               # K 循环不出核
+      Fixpipe: L0C → L2(写 L2 即完成,GM 回写可异步)
+
+

4.4 StreamK(K 维核间切分)

+

4.4.1 做什么

+

当 B、M、N 三个维度切到最碎仍填不满 32 核时,把 K 维切到核间:多核各算一段 K 的部分和,再归约:

+

$$ +C_{(\beta,\mu,\nu)} = \sum_{c \in group} C^{(c)}_{(\beta,\mu,\nu)} \quad \text{(部分和写 workspace,AIV 归约或原子加)} +$$

+

4.4.2 进入条件(两条缺一不可)

+

条件 1(并行缺口存在):不切 K 时的独立输出块数

+

$$ +P = B \times \lceil M / 16 \rceil \times \lceil N / 16 \rceil < C = 32 +$$

+

(源码实现取更保守的 $B \cdot mCnt \cdot nCnt \le aicNum/2$,并附加 ND-only、无交叉广播、确定性等级 ≤ 1(原子加顺序不定)等工程限制)。注意**严格的 StreamK 不要求核间完全不切 B/M/N**——它是一般框架 `grid_K × grid_B × grid_M × grid_N ≤ C`,纯切 K 只是 grid_B=grid_M=grid_N=1 的特例;当 B/M/N 能提供部分并行度时,应该用组合 grid 把归约组 $grid_K$ 压到最小(grid_K 小一档,K 的门槛降一档平方级)。

+

条件 2(归约代价可接受):每核计算时延须远大于归约时延(安全系数 α = 10):

+

$$ +T_{MMAD/core} \ge \alpha \cdot T_{Reduce} +\;\Longleftrightarrow\; +\frac{K}{grid_K} \;\gtrsim\; grid_K \times 1690 +$$

+

即 $K \gtrsim grid_K^2 \times 1690$:grid_K=2 → K ≥ 6.8K;grid_K=4 → K ≥ 27K;grid_K=8 → K ≥ 108K;grid_K=32 → K ≥ 1.7M(仅极端 case)。同时 $K / grid_K \ge 256$(单核 K 段过碎则 tiling 效率崩)。grid_K 越大对 K 的要求越苛刻——StreamK 内部的 grid 搜索自然淘汰归约过重的配置。

+

4.4.3 实现要点

+ +

4.4.4 与不切 K 分支的关系

+

StreamK 从不"硬切换"进入:当不切 K 的分支候选已足够快(如已 Cube Bound),StreamK 候选的归约开销使其自然落败;只有当 B/M/N 并行度不足导致大量核闲置时,StreamK 才以数量级优势胜出(例:B=1、M=N=64、K=65536 时,不切 K 仅 16 核可用,StreamK 32 核满负荷)。

+

4.5 ASW_Basic(通用切分框架)

+

4.5.1 做什么

+

不切 K,允许切 B/M/N 的任意组合——它是"不含 K 且含共享读取"的 6 种切分组合({M},{N},{M,N},{B,M},{B,N},{B,M,N})的统一实现框架,也是 B < 32 但 P ≥ 32 时的最优归宿,同时兜住 B ≥ 32 但 IterBatch/MergeBatch 条件不满足的剩余 case。B 可以大、可以小、可以等于 1;ASW_Basic 是实践中最常命中的分支。

+

4.5.2 核心机制:swizzle + L2 管理

+

切 M/N 的固有代价是共享矩阵的重复读,ASW_Basic 用两件武器把代价压到最低:

+
    +
  1. ASW 滑窗蛇形 swizzle:把 M 向按窗口 $W$ 分组($W = \max{d : d \mid C,\ d \le \lfloor\sqrt{C}\rfloor}$,32 核取 W=4),窗口内蛇形遍历 N 向。数学效果:同一时刻 32 个核活跃的工作集被压缩到"W 个 A 行块 + 一条 B 列块带",L2 足迹最小 ⇒ 共享读取基本命中 5.2TB/s 的 L2 而非 1.6TB/s 的 GM。窗口取 $\lfloor\sqrt C\rfloor$ 的最大因子,是因为窗口越接近正方形,A 行块 + B 列块的 L2 足迹越小,且因子性保证整窗被核数均分、窗口边界不碎;
  2. +
  3. L2 切分:工作集超过 128MB 时,按 mL2TileNum × nL2TileNum 切分,每个 L2 块错位分核(对角线分配),避免多核同时抢同一地址的读读冲突,并优先选拖尾小的方案。
  4. +
+

4.5.3 核间切分维度的选择顺序

+

按共享代价从低到高:

+
    +
  1. 切 B(B ≥ 核数):零共享,永远先试;
  2. +
  3. 切 M(B 不够):右矩阵 [K, N] 被共享,若 $KN \cdot \text{dtype} \le 128$MB 则驻留 L2,零 GM 重复读;
  4. +
  5. 切 N:对称;
  6. +
  7. 混合切(B×M、M×N、…):双向共享,靠 swizzle + L2 切分管理;
  8. +
  9. 降核:P 远小于 32 且 K 也不够格走 StreamK 时,宁可部分核闲置(小 case 时延绝对值小,调度开销反而主导)。
  10. +
+

4.5.4 内部特化(不是独立分支)

+ +
+

5. 分支仲裁与整体决策流程

+

5.1 为什么需要仲裁层

+

第 4 章的进入条件给出的是各分支的"主场",但主场之间有重叠区(例如 B ≥ 32 且 M×N 中等时,MergeBatch 与 IterBatch 都合法;B 较大时 IterBatch 与 ASW_Basic 切 B 等效)。重叠区的最优归属没有解析解,必须由统一的时延模型仲裁:

+

$$ +\text{branch}^* = \arg\min_{cand \in \bigcup \text{各分支候选}} \max\big(T_{MMAD}, T_{MTE2}, T_{MTE1}, T_{Fixpipe}[, T_{Reduce}]\big) +$$

+

分支体系的价值在于候选集完备且无冗余:每个等价类只派一个代表框架生成候选,时延模型在等价类内部和边界上做精细仲裁。两层缺一不可——只有模型没有分支,搜索空间是 15 种组合 × 全部 grid 参数的爆炸;只有分支没有模型,边界 case 被硬阈值误杀。

+

5.2 总决策流程

+
输入:B, M, N, K, dtype, layout, 广播形态, bias
+ │
+ ├─[0] K = 0 → AIV 清零;K = 1 → AIV 逐元素乘(TO_MUL 通路)
+ │
+ ├─[1] BatchB = 1 → 转Matmul(免费折叠 [B·M, K],必选)
+ │     BatchA = 1 → 比较"重排 B + Matmul" vs "广播友好 IterBatch/ASW",
+ │                  按时延模型选小者
+ │
+ ├─[2] BatchA = BatchB = B > 1:
+ │     生成四类候选并逐一估算 T_total:
+ │       MergeBatch(条件 1~6 全过才生成,见 4.2.2)
+ │       IterBatch(三大类条件,见 4.3.2)
+ │       ASW_Basic(按 4.5.3 顺序试切 B/M/N/混合,含 swizzle 与 L2 切分)
+ │       StreamK(P < 32 且 K 满足 4.4.2 条件 2 时生成,grid 搜索)
+ │     → argmin T_total
+ │
+ └─[3] 输出:分支 + tiling 参数(baseM/baseN/baseK、b、bL1、kL1…)
+       + swizzle 方案 + L2 切分方案 + 预估端到端时延
+
+
+

6. 五大分支设计的完备性审视(漏洞检查)

+

按"转Matmul / MergeBatch / IterBatch / StreamK / ASW_Basic 五大分支 cover 全部 BMM case 最优实现"的设计目标,逐条拷问。

+

6.1 覆盖矩阵:无空洞

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
shape 区域主分支兜底
K = 0 / K = 1前置通路层(AIV)
BatchA=1 或 BatchB=1转MatmulASW_Basic(广播友好形态)
BatchA=BatchB>1,B≥32,M×N 大IterBatchASW_Basic 切 B
BatchA=BatchB>1,B≥32,M×N 小,访存 BoundMergeBatchIterBatch
上述但 B<32,P≥32ASW_Basic降核 ASW
P<32,K 大StreamK降核 ASW
P<32,K 也小降核 ASW_Basic(此时时延绝对值小,调度开销主导,分支选择不敏感)
交叉广播(BatchA≠BatchB 且均>1)ASW_Basic
+

6.2 审视发现的问题与修正

+

设计骨架成立,但有五处需要修正或显式声明,否则会被反例拷问:

+

问题 1:转Matmul 的方向不对称(原设想的最大漏洞)。 "一侧 batch=1 就折叠成 Matmul"在 BatchB=1 方向免费(batch 与 M 内存相邻,输出布局一致);但在 BatchA=1 方向,右矩阵 [B,K,N] 折叠成 [K,B·N] 需要一次真实的转置重排,且输出 [M,B·N] 与目标 [B,M,N] 之间存在置换——"只是输出后按 batch split"的设想在 ND 布局下不成立,split 实际是 scatter。修正:BatchA=1 时按"重排代价 vs Matmul 收益"走模型仲裁,小 case 留在 BMM 分支内(A 单侧数据天然可 L2/L1 驻留共享,本身已接近最优)。

+

问题 2:交叉广播 case 的归属必须显式声明。 BatchA=(6,1)、BatchB=(1,6) 这类 case 既不进转Matmul(两侧都>1),也不满足 MergeBatch/IterBatch 的 BatchA=BatchB 前提——它们落入 ASW_Basic(对广播侧做驻留)。不声明就会显得"五分支有洞"。声明后完备性闭合。

+

问题 3:K 退化不在五分支内,需前置通路层。 K=0(无计算)、K=1(无累加深度)走 AIV 向量通路;这是"计算通路选择"维度,与"切分维度"正交,放在五分支之前判断。源码用 K_EQUAL_ZERO / TO_MUL 两个独立策略处理,印证了这一层的必要性——但它们是通路切换而非新切分等价类。

+

问题 4:IterBatch 草稿条件 3(2) 的字面表述有误杀。 B mod aicNum > minCoreNum 会拒绝 B 整除核数的完全均衡 case(余数 0)。正确表述应以负载均衡比为准:访存 Bound 要求 bAvg/bMax > 0.8,计算 Bound 要求 100%;余数规则只是它的近似操作化。

+

问题 5:经验常数必须可标定,且源码硬编码条件偏粗。 $b_{thr}=4$、$k_{thr}$=32B/dtype、480KB、16KB、dValue≥256B 都是 DV100 档芯片的实测经验值,文档中全部显式参数化(换芯片只换常数表)。对照之下源码把 batchC ≥ 4×aicNumalignK ≥ 64M ≤ N 等直接写死,其中 alignK ≥ 64 比草稿阈值保守 4 倍、M ≤ N 放弃了镜像 case——做最优实现时不应继承这些硬编码,而应按第 4 章的条件体系重新判定

+

6.3 与源码 10 策略的关系

+

源码 arch35 的 10 个策略(K_EQUAL_ZERO / TO_MUL / STREAM_K / MERGE_BATCH / ITER_BATCH_BROADCAST / ITER_BATCH / AL1_FULL_LOAD / BL1_FULL_LOAD / ASW_BASIC / BASE)与本文五分支不是同层概念:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
源码策略本文归属
K_EQUAL_ZERO、TO_MUL前置通路层(4.0),正交于切分
STREAM_KStreamK
MERGE_BATCHMergeBatch
ITER_BATCH、ITER_BATCH_BROADCASTIterBatch(broadcast 变体是广播输入下的数据复用特化;单边广播在本文更多由转Matmul 吸收)
AL1_FULL_LOAD、BL1_FULL_LOADASW_Basic 的 L1 驻留参数极限(4.5.4)
ASW_BASIC、BASEASW_Basic
+

结论:源码策略集 = 五分支 × 计算通路 × 驻留/广播特化的展开。五分支是"切分等价类"的最小完备骨架,源码的冗余策略可在新实现中收敛,源码遗漏的(条件 3/4/6 的显式判定、M>N 的 MergeBatch 镜像、转Matmul 的 BatchA=1 方向)正是优化的增量空间。

+
+

7. 总结

+
    +
  1. 最优的定义:$T_{total} = \max(T_{MMAD}, T_{MTE2}, T_{MTE1}, T_{Fixpipe}[, T_{Reduce}])$ 最小;瓶颈交换是合法且必要的手段。
  2. +
  3. 分支的推导:4 维可切 → 15 种组合完备 → 切分特征表(切 B 免费 / 切 M/N 廉价被 L2 吸收 / 切 K 昂贵需归约)→ 按价格从低到高购买并行度 → 坍缩为 MergeBatch、IterBatch、ASW_Basic、StreamK 四个等价类,加前置的转Matmul 问题归约层,共五大分支,完备且极小
  4. +
  5. 各分支的条件都不是孤立经验,而是"资格(并行度够不够)→ 上限(容量/算存比封顶)→ 下限(搬移效率托底)"三层逻辑的实例化;所有经验常数可标定、可移植。
  6. +
  7. 边界不靠硬切:重叠区由端到端时延模型统一仲裁,分支体系负责候选集的完备无冗余。
  8. +
  9. 设计经受了漏洞拷问:修正了转Matmul 的方向不对称与 IterBatch 均衡条件的字面误杀,显式声明了交叉广播与 K 退化的归属;相对源码实现,本文条件体系更细、更真、覆盖更全。
  10. +
+
+

参考文档:《BMM分块计算数学公式》《BMM最优软件实现方案设计》《BatchMatMulV3算子分支实现分析》《BMM从分块计算到四大分支的逻辑推导》;源码:ops-nn/matmul/batch_mat_mul_v3(arch35);芯片资料:昇腾 950PR 架构白皮书与 CANN 9.0.0 性能建模文档。

+ +
+ +