2318 字
约 7 分钟
7
S23-J13 · 加速器:计算单元与存储层次

适用读者:要判断"这块卡为什么跑不满"、要选卡或要读 kernel 性能报告的人。
前置:S23-J07、J12(单步估算与训练账)。
覆盖旧文:A-4337 §4.1–§4.3(从模型计算认识加速器 + 计算单元 + 存储层次,312 点)→ 312 点。
扩展点:E-S23-035(算术强度与 roofline 阈值:M* ≈ 344 token)、E-S23-036(形状效率 η_shape:补零让 MoE 多算 8 倍)、E-S23-037(容量不等式与 B_max)、E-S23-038(面积/功耗预算:TPU v1 的 37% 缓冲 vs 30% 计算)。
上一篇:S23-J12 · 训练负载、RL 与预算
下一篇:S23-J14 · 数据搬移与多芯封装互联。


1. 一句话结论

同一份权重,M=1 时算术强度约 1 FLOP/byte,M=256 时 228 FLOP/byte,而 H100 的分水岭是 295。 所以 decode 的瓶颈几乎必然在搬数据,不在算;而"把卡换成算力更高的型号"对 M=1 毫无帮助。

出处:AI Infra 教材 §4.1–§4.3(id 4337),模型 Qwen3-8B。

算术强度 I = F / V(FLOP per byte)
机器分水岭 I* = 峰值算力 / 峰值带宽
I < I* → 带宽受限;I > I* → 算力受限

2. 一次 Q 投影的算术强度(E-S23-035)

Y = XW_Q,X:[M,4096],W_Q:[4096,4096],Y:[M,4096]

F = 2MKN = 2M × 4096² = 33,554,432·M FLOPs
V = 2MK + 2KN + 2MN = 33,554,432 + 16,384·M  bytes
   (输入一次 + 权重一次 + 输出一次,均 BF16)
一次 Q 投影 M=1 M=256
计算量 33.6 MFLOPs 8.59 GFLOPs
权重读取 32 MiB 32 MiB
输入读 + 输出写 16 KiB 4 MiB
总访问量 ~32 MiB ~36 MiB
算术强度 ≈ 1.0 FLOP/byte ≈ 227.6 FLOPs/byte

判据:行数 ×256,算力 ×256,访问量只涨 1/8。 权重复用是"算力长在带宽上"的唯一途径——这就是 batch 的全部意义。

2.1 H100 的分水岭

I* = 989.4 TFLOP/s ÷ 3.35 TB/s ≈ 295 FLOP/byte
情形 I 谁受限
M=1(decode) ~1 带宽(差 295 倍)
M=256 ~227.6 仍偏带宽
M≈345 ~295.3 刚好吃平

判据:这个 4096×4096 投影要一次处理约 345 个 token 才够"喂饱"H100。 单请求 decode 永远达不到——只能靠 batch 或更大的矩阵。


3. 计算单元:矩阵与向量分工

Transformer 层的两类计算交替出现:
矩阵:投影、QKᵀ、PV(规则乘加,块内复用)
向量:归一化、RoPE、Softmax、门控激活(逐元素、特殊函数、归约)

注意力就是 矩阵 → 向量 → 矩阵:QKᵀ(矩阵)→ Softmax(向量)→ PV(矩阵)。

3.1 两种架构的分工对照

维度 NVIDIA GPU(CUDA 高性能路径) 昇腾 DaVinci
矩阵计算 SM 内 Tensor Core 处理 tile Cube 处理矩阵 tile;Vector/Scalar 处理逐元素、归约、控制
全局→片上 L2/L1 通常硬件管理;可显式用 shared memory、异步拷贝、TMA MTE/NDDMA 按描述符在 Global / L1 / UB / L0 之间搬移,路径由算子或编译器规划
部分和 寄存器、shared memory 或专用矩阵存储 L0C 保存 Cube 部分和
搬移与计算重叠 memcpy_async、TMA、barrier、pipeline MTE 与 Cube/Vector 通过 flag/event 同步
同步层级 warp / block / cluster / device 核内阶段、Cube/Vector 交接、核间协议
软件承担 高性能路径仍需安排 tile、共享内存、布局、异步依赖 更早面对 L1/UB/L0 容量与交接(Developer 模式可自动插同步)

判据:GPU 把"缓存"交给硬件、把"复用"留给软件;DaVinci 把"路径"显式化给编译器和算子。 责任边界不同,不是谁更先进。


4. 形状效率:补零吃掉多少算力(E-S23-036)

矩阵指令按固定块执行(比如行方向最小 16 行),不足整块补零:

η_shape = M·N·K / (⌈M/m_t⌉·m_t · ⌈N/n_t⌉·n_t · ⌈K/k_t⌉·k_t)

MoE 的例子(原文数):64 个 token × 每 token 8 个专家 = 512 次分派,行补齐 16。

路由 每专家行数 实际执行行数 有效行
均匀覆盖 256 专家 2 256×16 = 4,096 512
集中到同一组 8 专家 64 8×64 = 512 512
有效计算量相同,执行量差 8 倍(4096 vs 512)

判据:"负载均衡"在系统层是好事,在 kernel 层是灾难。 均匀路由让每个专家只剩 2 行有效数据,14/16 的乘加在算零——这正是 J10 里"集中路由省 32 倍权重读取"的另一半原因。


5. 存储层次与容量(E-S23-037)

常驻权重 W_resident + 每请求 KV (B·S·m_KV) + 工作区 M_workspace ≤ 可用容量 C

B_max = ⌊(C − W_resident − M_workspace) / (S · m_KV)⌋
m_KV = 144 KiB/token(Qwen3-8B,BF16)

RTX 4090(24 GB)实例,取工作区 2 GiB:

项 数值
权重(BF16) 16.4 GB
剩余给 KV 约 5.47 GB
8K 上下文单请求 1.125 GiB ≈ 1.21 GB
4 条 8K 请求 约 4.83 GB ✅
5 条 8K 请求 约 6.04 GB ❌
16K 上下文 每条翻倍 → 2 条

判据:容量是"不等式 + 向下取整",不是"估算个大概"。 多加一条请求越界,整批就会 OOM——所以服务端宁可少放一条。

5.1 三个问题要分开问(原文强调)

问题 看什么
放得下吗 容量不等式(权重 + KV + 工作区)
重复使用时从哪一级读 寄存器 / 共享内存 / L2 / HBM 的路径
独立访问够不够维持带宽 并发访问数 × 每访问字节数 vs 带宽

6. 面积与功耗:为什么缓冲比计算单元还大(E-S23-038)

TPU v1 的面积分布(原文引论文):

部件 面积占比
统一数据缓冲(24 MiB) 37%
计算单元(256×256 8-bit MAC) 30%
控制电路 2%

缓冲面积超过计算单元——因为阵列要反复使用输入、权重和部分和;若每次从片外读,乘加器就会长时间等数据。

6.1 Amdahl 的复利递减

S = 1 / ((1−f) + f/s)
f=0.6, s=2 → 1/(0.4+0.3) = 1.43
再翻到 4 → 60/4 + 40 = 55 μs(第一次省 30 μs,第二次只省 15 μs)
上限:矩阵时间→0 时仍是 2.5×

判据:局部加速的收益递减,且被"没加速的那部分"封顶。 优化前先确认 f 有多大,否则投的资源全花在 40 μs 的尾巴上。


7. 可复算(实测)

$ cd /root/博客运营官/blog-v2 && python3 tools/s23_book_calc.py | tail -11
Q 投影 4096×4096(BF16)
  M=1   : F 33.55 MFLOPs, V 32.02 MiB, I = 1.0 FLOP/byte
  M=64  : F 2147.48 MFLOPs, V 33.00 MiB, I = 62.1 FLOP/byte
  M=256 : F 8589.93 MFLOPs, V 36.00 MiB, I = 227.6 FLOP/byte
  H100 I* = 989.4/3.35 = 295.3 FLOP/byte → M* ≈ 345 token
  η_shape(16 行补齐): 均匀 256×16 = 4096 行 / 集中 8×64 = 512 行 → 8.0×
  RTX 4090 24 GB: 权重 16.38 GB, 剩余 5.47 GB;8K 单请求 1.21 GB
    4 条 8K = 4.83 GB 可行
    5 条 8K = 6.04 GB 超限
    16K: 每条 2.42 GB → 可放 2 条

8. 前提与边界

结论 成立条件 不成立时
I* = 算力/带宽 单卡、无片上复用 数据已在 L2/共享内存 → 有效带宽更高
M*≈345 4096×4096 投影、BF16 不同形状、不同卡 → 重算
容量向下取整 每请求等长 变长请求 → 按 p95 长度算
补零浪费 8 倍 行最小 16、每专家 2 行 换 GEMV/分组 kernel → 浪费减少

9. 常见误区

误区 纠正
换更高算力的卡就能提速 decode M=1 时 I≈1,算力根本用不上
认为 batch 只是"提高吞吐" 它把 I 从 1 提到 228,是改变瓶颈性质
用峰值 TFLOPs 估实际性能 要先过 roofline 与 η_shape 两道折扣
忽略补零 MoE 均匀路由下执行量是有效的 8 倍
显存按"权重 + 一点余量"估并发 必须写容量不等式并向下取整

10. 自测

  1. M=64 时该投影的算术强度大约多少?H100 上算力还是带宽受限?
  2. H100 的 I* 是多少?为什么 M=256 仍然"偏带宽"?
  3. 64 token × 8 专家、行补齐 16,均匀路由执行多少行?有效多少行?
  4. RTX 4090 上跑 Qwen3-8B(BF16)、工作区 2 GiB、上下文 8K,最多几条并发?
答案
  1. I ≈ 62.1(实测);远低于 295,仍带宽受限。
  2. 989.4/3.35 ≈ 295.3;M=256 只有 227.6,差 22.9%。
  3. 256×16 = 4,096 行执行,512 行有效(8 倍浪费)。
  4. 剩余约 5.47 GB,每条 8K 约 1.21 GB → 4 条。

11. 下一篇

S23-J14 · 数据搬移与多芯封装互联 —— 数据从哪来、经过哪几级、用什么带宽;多芯片封装(NVLink/超节点)为什么把"内存池"变成可能。

S23-J13 · 加速器:计算单元与存储层次
https://www.clxhxhhr.top/posts/5540/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。