首页优化地图方法索引基础概念
返回技术汇总表 ↗

M006 · 独立详解

矩阵乘法与访存优化:把数据搬进来,多用几次

从一个4×4乘法理解分块,再看真实Linear的形状、搬运流水和内核选择。

算子与编译内存与数据搬运详解已编写
视频讲解待制作

这篇文章的小视频尚未制作;可以先阅读下方文字详解。

本页目录

01 · Linear到底在算哪张表

设输入X形状[M,K]、权重W形状[K,N],输出Y=XW形状[M,N]。M是本次一起处理的token行数,K是输入宽度,N是输出宽度。每个Y[i,j]需要把X的第i行与W的第j列做长度K的点积。这里采用数学布局,真实框架权重可能存成[N,K]并以转置语义调用。

按乘法和加法各计一次,工作量约2MNK FLOP。优化GEMM一般不减少这个数学工作,而是减少重复搬运、提高矩阵单元使用率,并安排更多合适的并行任务。前向和反向分别有不同shape,不应仅按模型参数量挑内核。

运算教学shape作用
前向Y=XW[M,K]×[K,N]产生输出。
输入梯度dX=dY Wᵀ[M,N]×[N,K]把梯度传给前层。
权重梯度dW=Xᵀ dY[K,M]×[M,N]汇总所有token对权重的贡献。

依据:NVIDIA · GEMM形状、算术强度与分块背景 ↗

02 · 最直观实现为什么反复读同一个数

教学示意 · 不代表硬件实测
for i in range(M):
    for j in range(N):
        acc = 0
        for k in range(K):
            acc += X[i,k] * W[k,j]
        Y[i,j] = acc

自设4×4乘4×4:16个输出各读4个X和4个W,总共128次输入元素读取、16次输出写入。X[i,k]其实会被同一输出行的4列重复使用;W[k,j]也会被4个输出行使用。

这个计数把每次索引读取都当成访问,不模拟硬件缓存。真实朴素实现也可能命中缓存,所以128不能直接作为实际HBM事务;它用于暴露可复用的数据。

依据:Triton · 分块矩阵乘法官方教程 ↗

03 · 分块:一小块输入,贡献给多个输出

用2×2输出块举例:把2×2的X块和2×2的W块搬到工作区,两块各4个数就能更新4个输出。沿K方向继续搬下一块、累加到同一输出块,最后才写回。这块X服务2列输出,W服务2行输出。

教学示意 · 不代表硬件实测
for each output tile (rows, columns):
    accumulator = zeros(tile_M, tile_N)
    for each K tile:
        A_tile = load(X[rows, k_range])
        B_tile = load(W[k_range, columns])
        accumulator += A_tile @ B_tile
    store(Y[rows, columns], accumulator)

4×4例子中,2×2块有4个输出块,每块沿K走2次,每次搬8个输入元素,共64次;4×4整块只读完整X/W各一次,共32次。乘加次数保持不变,复用越多,工作区也越大。

4×4输出,切成多大的块?

4×4乘4×4,沿M/N/K均用相同tile;只数每次加载输入tile,忽略跨块缓存。工作区按单缓冲A/B/累加器各4B元素计,不代表硬件分配大小。

真实内核还有多级分块:设备内存到片上共享/缓存、再到寄存器或矩阵单元。不同输出块可能在更高层缓存里继续共享输入,不要求每块都从HBM重新读取。

依据:NVIDIA CUTLASS · 高效GEMM层级与流水 ↗ · Triton · 分块矩阵乘法官方教程 ↗

04 · 为什么Decode和Prefill要用不同策略

先做一个理想完整张量账本:输入和输出都按2B/元素、只读X/W并写Y一次,字节为2(MK+KN+MN),算术强度I=2MNK/字节。它是简化参照,不包含缓存复用、工作区和重复读取。

K=N=4096计算量理想字节I / FLOP每字节
M=1约33.55 MFLOP约32.02 MiB约1.00
M=128约4.29 GFLOP34 MiB约120.47
M=4096约137.44 GFLOP96 MiB约1365.33

M=1时,完整权重服务一行输入,权重读取成本很突出;M增大时同份权重服务更多行,计算/搬运比例上升。普通单请求Decode每次只增加少量行,批处理能改变M,但会引入排队与每轮耗时取舍。

大M并非永远更快:它要做更多工作。这里说明吞吐效率为什么可能改善,不是建议为减少延迟无条件扩大批量。低精度、权重缓存、融合与并行切分都会改变实际瓶颈。

依据:NVIDIA · GEMM形状、算术强度与分块背景 ↗ · NVIDIA CUTLASS · 高效GEMM层级与流水 ↗

05 · 大块更省搬运,也可能减少并行度

一个输出块对应一个或若干执行任务。更大块通常有更多输入复用,但块数更少、寄存器和片上容量需求更高。矩阵很小时,大块可能只产生少数任务,让其他计算单元空闲。

边界尺寸不能被tile整除时,要用mask或补齐,并核对新增存储和计算。若沿K切成多个独立任务,还需合并局部和;这是GEMM的Split-K,不等于Attention的Split-KV。训练dW的归约形状也可能适合不同策略。

  • shape:M/N/K、转置和stride;不能只看元素总数。
  • dtype:输入、累加、输出分别记录;调用高吞吐矩阵单元要匹配支持条件。
  • 资源:输出tile数、片上工作区、寄存器、并发与边界浪费。
  • 后处理:bias/激活融合、其他消费者和训练保存是否允许。

依据:NVIDIA CUTLASS · 高效GEMM层级与流水 ↗ · Triton · 分块矩阵乘法官方教程 ↗

06 · 双缓冲:算这块时,准备下一块

单缓冲可能是“搬块0→算块0→搬块1→算块1”。双缓冲用两个槽:矩阵单元算槽A时,搬运单元准备槽B;A读完才能再次写A,B搬完才能用B。理想情况下稳态受较慢阶段主导,而不是每块搬运和计算全串行。

教学示意 · 不代表硬件实测
预加载 tile0 到槽A
for each K tile:
    等当前槽可读
    在独立槽预取下一tile(存在且槽可写时)
    用当前槽乘加到accumulator
    标记当前槽不再被计算读取
最后等待累加完成,再写输出

多缓冲增加片上占用,可能减少同时驻留的任务;异步下发也不会省掉依赖。搬运与计算还可能争用资源,所以不能把“开双缓冲”当作保证提速的按钮。

依据:NVIDIA CUTLASS · 高效GEMM层级与流水 ↗ · Ascend C · Matmul Tiling调优案例 ↗

07 · 用小脚本核对分块、边界和反向

下载脚本比较直接点积与分块GEMM,覆盖不能整除的shape;计数4×4例子的逻辑读取。另对Loss=½ΣY²求dX/dW,用分块乘法和有限差分对照。它没有调用设备矩阵单元,不测硬件速度。

教学示意 · 不代表硬件实测
先记录实际Linear的M/N/K、dtype、stride
建立正确输出/梯度基线
比较后端默认GEMM与候选tiling/流水策略
计时前热身,控制编译/调优成本是否计入
记录核心kernel与布局转换/临时缓冲
最后在完整模型路径复测

优先从cuBLAS/CUTLASS、框架编译后端或昇腾Matmul接口的适配实现阅读,再针对确实成为瓶颈的shape调优。一次小shape基准的最佳方案不能直接覆盖所有Prefill、Decode和训练反向。

依据:Triton · 分块矩阵乘法官方教程 ↗ · Ascend C · Matmul Tiling调优案例 ↗

08 · 怎样证明收益来自复用或更好的计算

目标证据
正确性同shape/精度的输出与梯度;边界、转置、bias和别名条件。
搬运实际读写字节、缓存命中和布局转换,不把逻辑读取数当硬件流量。
计算矩阵单元忙碌、任务数、每tile工作量与资源限制。
端到端训练step或服务延迟/吞吐;计入编译、转换、工作区和后处理。

减少HBM读取却变慢,可能是任务过少或同步更多;核心Matmul更快但整个Linear更慢,可能是新增布局转换。应以完整路径验证。

09 · Tensor Core与Cube:理念相通,参数不同

NVIDIA的矩阵单元、寄存器/共享存储和CUTLASS层级,与昇腾Cube、L1/L0及搬运流水有各自接口和布局要求。分块复用、独立预取和边界处理是共同思路;同一个tile尺寸、对齐规则和流水深度不能跨型号直接照搬。

昇腾官方Matmul调优资料提供Tiling、纯Cube、多核切K及矩阵共享等入口。平台对照应记录具体芯片、库版本、shape、dtype与总路径,而不是把理论峰值直接作为实际Linear吞吐。

依据:CANN商用版8.5.0 · Matmul性能优化入口 ↗ · Ascend C · Matmul Tiling调优案例 ↗ · NVIDIA CUTLASS · 高效GEMM层级与流水 ↗

  • 为什么4×4整块的输入读取减少,但乘加次数没变?
  • M=1的Linear,为什么仅提高矩阵算力未必明显变快?
  • 双缓冲什么时候不能覆盖搬运?什么时候反而挤占太多片上空间?

流程位置与关联方法

这个方法可能出现在多个位置;计算线包含模型计算与算子实现,执行线包含运行时、内存和通信。

资料与核查范围

原理依据以原始论文和官方文档为主;算例与时间线是教学推导。文档核查日期:2026-10-10。引用 main / latest 文档时,实际接口以安装版本为准。

代码为接入片段或教学伪代码;本页没有声称完成 NVIDIA / 昇腾硬件实测。

← 返回总表中的 M006继续阅读:FlashAttention 类精确注意力内核 →
AI Infra 知识库 · 总览 → 独立讲解网站更新 2026-10-08
搜索知识库

搜索方法与基础概念 · Esc 关闭