不包含LLM系统加速背景的版本:

问题描述

现有一个计算流程,包含三个串行执行的矩阵乘:

输入 X: [M, H]

算子1 (降维): Y = X @ A        其中 A: [H, r],  Y: [M, r]
算子2 (升维): Z = Y @ B        其中 B: [r, H'], Z: [M, H']
算子3 (主干): W = X @ C        其中 C: [H, H'], W: [M, H']

最终输出: O = W + Z    即 O: [M, H']

其中 r 远小于 HH'(例如 r=8, H=4096, H'=4096, M=64)。

由于 r 很小,算子1和算子2的计算量非常小,无法充分利用GPU的计算资源。三个算子串行执行时,算子1和算子2各自都只能用到GPU的一小部分算力,但它们仍然各自占用一次kernel launch和一次完整的显存读写。

目标

将算子1(降维矩阵乘)与算子3(主干矩阵乘)融合成一个Triton kernel,使得:

本质上,就是把算子1和算子3融合成一个算子。可以自己设置几个参数,先用Triton生成三个算子,完成算子1和算子3的正确融合,再往下做

具体效果

假设一个GPU上有80个SM,是否可以支持发射160个block,block 1 - 40完成计算部分1,block 41-80完成计算部分2,block 81-120完成计算部分1,block 121-160完成计算部分2;然后每个block内进行persistent thread block编程。通过这样的形式,是否可以支持两个block完成相应SM划分调度?

Concise answer: 思路是对的,但不完全可靠。你假设的是调度器按 pid 顺序做 round-robin 填充(pid 0→SM0, pid 1→SM1, ..., pid 79→SM79, pid 80→SM0, pid 81→SM1, ...)。如果这个假设成立,那你的方案确实能让每个 SM 上同时驻留一个 Part1 block 和一个 Part2 block。问题在于:NVIDIA 不保证这个调度顺序,但在实践中它大致成立

方案图解

Launch 160 blocks, GPU 有 80 SMs, 每个 SM occupancy = 2 blocks

假设 round-robin 调度:

第一轮 (pid 0-79):
  SM0  ← pid 0  (Part1)
  SM1  ← pid 1  (Part1)
  ...
  SM39 ← pid 39 (Part1)
  SM40 ← pid 40 (Part2)
  SM41 ← pid 41 (Part2)
  ...
  SM79 ← pid 79 (Part2)

第二轮 (pid 80-159):
  SM0  ← pid 80  (Part1)
  ...
  SM39 ← pid 119 (Part1)
  SM40 ← pid 120 (Part2)
  ...
  SM79 ← pid 159 (Part2)

实现步骤

Step 1:确定目标矩阵维度并Profile

以Llama3-8B模型、batch size=64为参考场景,确定各矩阵的具体维度。仅仅关注以下线性层的M/N/K:gateup_proj。降维秩 r=8