GEMM 三向分块参数 M/N/K BlockSize 完整解释
GEMM 公式:CM×N=AM×K×BK×NC_{M×N} = A_{M×K} × B_{K×N}CM×N=AM×K×BK×N
三个维度对应三套分块参数:
- M_block:A 矩阵行维度分块大小(选项A)
- N_block:B 矩阵列维度分块大小(选项B)
- K_block:矩阵乘累加维度分块大小(选项C)
一、每个参数分别是什么含义
1. M方向分块大小 M_block(A的行、C的行)
- 逻辑:矩阵 A 维度 M,把 M 切多段,每段长度 = M_block
- 硬件对应Task Block(AI Core并行分块)
多个AI Core并行,每个Block只算 M_block 行的数据,各核负载拆分。 - 存储:每块 A[M_block, K] 会搬入 L0A
2. N方向分块大小 N_block(B的列、C的列)
- 逻辑:矩阵 B 维度 N,把 N 切多段,每段长度 = N_block
- 硬件对应单AI Core内一次输出的C矩阵宽度
- 存储:每块 B[K, N_block] 搬入 L0B;输出 C[M_block, N_block] 存在 L1
3. K方向分块大小 K_block(累加维度,乘加循环)
- 逻辑:A、B公共维度K,循环多次累加,每次只取 K_block 长度做Cube乘;
A(M,K)×B(K,N)=∑tile=0K/KblockAtile(M,Kblock)×Btile(Kblock,N)A(M,K)×B(K,N) = \sum_{tile=0}^{K/K_{block}} A_{tile}(M,K_{block}) × B_{tile}(K_{block},N)A(M,K)×B(K,N)=∑tile=0K/KblockAtile(M,Kblock)×Btile(Kblock,N) - 核心约束:L0A、L0B容量上限完全由 K_block 决定
L0A存 M_block × K_block;L0B存 K_block × N_block;两者总和不能超过片上L0总大小。
二、为什么这三个参数必须确定?(对应Local内存、Cube、硬件限制)
1. 硬件存储硬性约束(最核心原因)
昇腾Cube计算必须把A、B小块放入L0A / L0B(Local专用缓存),L0容量极小(MB级),不能一次性放下完整矩阵。
{L0A占用=Mblock×Kblock×data_type_bytesL0B占用=Kblock×Nblock×data_type_bytes \begin{cases} \text{L0A占用} = M_{block} × K_{block} × \text{data\_type\_bytes}\\ \text{L0B占用} = K_{block} × N_{block} × \text{data\_type\_bytes} \end{cases}{L0A占用=Mblock×Kblock×data_type_bytesL0B占用=Kblock×Nblock×data_type_bytes
三者任意一个太大,都会直接 Local Memory Overflow 报错;
三者搭配太小,会频繁SDMA搬运Global→L0,访存瓶颈。
2. 匹配Cube硬件原生计算粒度
达芬奇Cube最小硬件计算单元为 16×16×16(FP16):
- M_block、N_block 建议是16倍数,适配单次Cube输出块;
- K_block 建议16倍数,保证Cube流水线满载,减少计算气泡。
三个分块尺寸不对齐16,会产生填充0、算力浪费,msprof中CubeUtilization变低。
3. 控制SDMA搬运次数,决定访存开销
- K_block 越小:外层K循环次数越多,Global ↔ L0 来回搬运越频繁,HBM带宽压力暴增;
- M_block / N_block 太小:单次Cube计算数据量少,流水线频繁启停,PipeUtilization流水线利用率下降。
4. 控制多AI Core并行负载均衡(M_block)
总M长度 / M_block = 启动的Task Block数量(AI Core并行数)。
M_block设置不合理会导致:AI Core数量不匹配硬件、部分核负载过重、部分核空闲,并行效率低。
5. 控制L1输出缓存占用(M_block × N_block)
计算结果C存在L1,Mblock×NblockM_{block}×N_{block}Mblock×Nblock不能超过L1剩余容量;
如果M/N分块过大,L1溢出,必须频繁写回Global,增加带宽开销。
三、三者分工总结
- M_block(A选项)
负责多AI Core并行拆分,约束L0A、L1输出行宽; - N_block(B选项)
负责单次Cube输出宽度,约束L0B、L1输出列宽; - K_block(C选项)
控制内层累加循环次数,决定L0总占用、数据搬运频次,是调优GEMM性能最关键参数。
四、一句话总结为什么三者都需要确定
GEMM计算依赖片上极小L0/L1存储,必须把大矩阵沿M/N/K三维切小块;M/N/K分块大小共同决定:
① L0/L1内存是否溢出;
② Cube硬件计算是否对齐、算力利用率高低;
③ Global与Local之间数据搬运次数与带宽开销;
④ 多AI Core并行负载是否均衡。
三者缺一不可,都需要人工指定/自动Tiling求解。