AI Pulse

分块矩阵乘法真正的功课不在乘法,在数据复用

分块矩阵乘法真正的功课不在乘法,在数据复用

1. 2D分块矩阵乘法

昨天学习reduce_rows_2d时感觉熟悉,因为每个线程块仍然只拥有单行并执行一维求和。分块矩阵乘法完全打破了这一心智模型。

我们不会把一个线程块交给$C$的单行,而是交给它一个$C$的矩形:形状为(TM, TN)的输出分块。(bid.x, bid.y)成为该子矩阵的二维分块坐标(i, j)。为了计算它,线程块沿K维度以TK为步长扫描,从A和B加载匹配的面板,并用ct.mma累加部分乘积。这就是迈向真正二维计算的跨越:输出分块所有权与沿K的内部收缩配对,而不是“一行、一次归约”。

2. 核函数实际在做什么

去掉tiled_view等便捷封装后,核心算法是显式的:
- 网格启动:形状(tiles_M, tiles_N)确保C中每个输出分块恰好有一个属主线程块。
- 初始化:累加器acc = zeros((TM, TN), dtype=float32)位于快速存储/寄存器中。
- K循环:
- 加载形状为(TM, TK)的A面板,分块索引为(i, k)。
- 加载形状为(TK, TN)的B面板,分块索引为(k, j)。
- 累加:acc = ct.mma(A_panel, B_panel, acc)。
- 写回:将完成后的acc存储到C的(i, j)分块处。

3. 为什么这比另一个归约更重要

行归约培养坐标读写能力;矩阵乘法培养数据复用与内存层级意识。
- 数据复用:每个A面板被多个列分块j复用;每个B面板被多个行分块i复用。
- 带宽节省:K循环是分块GEMM存在的唯一原因。它让高写入量的输出分块驻留在寄存器中,同时流式输入数据,避免了对高带宽内存(HBM)反复进行的昂贵往返。
- 硬件对齐:这就是Tensor Core模式出现的地方。ct.mma成为将分块索引直接连接到现代硬件矩阵加速引擎的桥梁。

4. Nsight Systems:不要再分析你期望的故事

写完核函数后,我们将Nsight Systems(nsys)指向vector_add,并以最好的方式被上了一课。执行时间线并非由原始计算主导,而是充满了:Python运行时开销 -> cudaMalloc -> cuLibraryLoadData -> curand -> 最后才是vector_add的一个小点。

CUDA API vs. CUDA硬件

看到可视化后的分裂,区别立刻变得明显:
- API行:主机(CPU)发出CUDA命令——分配、运行时编译、内核启动和同步。
- 硬件行:GPU在流多处理器上实际处理线程束。

第一次启动在主机时间线上往往看起来灾难性(数百毫秒),仅仅是因为驱动初始化、模块加载和JIT编译。即使在硬件行,第一次内核调用也会产生开销(冷运行约35微秒,热运行约6微秒),原因包括冷缓存、首次页面访问和时钟频率爬坡。这是两种完全不同的“首次调用”成本。

Nsight Systems用一句话说:找出真实墙钟时间消失在哪里,并判断GPU到底是饱和、停滞还是因CPU工作不足而挨饿。

5. 这在阶梯上的位置

- 第一阶段:1D带宽内核(Vector Add, Scale, SAXPY)
- 第二阶段:1D树归约和softmax
- 第三阶段:2D行归约(索引桥梁)
- 当前:分块矩阵乘法作为真正2D计算的入口,搭配nsys进行全时间线分析
- 下一步:对GEMM tmr进行主动回忆,扫描分块维度(TM, TN, TK),然后在nsys识别出关键内核后,使用Nsight Compute(ncu)检查硬件级瓶颈。

要点:2D行操作只是借助1D直觉。分块矩阵乘法需要一种新的数据复用和分块所有权心智模型。一旦内核编译完成,nsys就是那个现实检查,告诉你调整该内核是否真的能推动指针。

阅读原文
📚 相关主题 AI推理

订阅 AI Pulse

每天 08:00 · 12:30 · 18:30 · 23:50 更新