跳转到主要内容

Compute-bound vs Memory-bound:推理的两大瓶颈

1. 核心概念:两种瓶颈

GPU 执行任何计算都涉及两件事:

  1. 计算:ALU 做矩阵乘法等运算(受 TFLOPS 限制)
  2. 访存:从显存读取数据到计算单元(受 HBM 带宽限制)
┌──────────────┐                    ┌──────────────┐
│   HBM 显存    │ ──── 带宽 ────→   │   计算单元    │
│  (存权重/KV)  │  (Memory BW)      │  (做矩阵乘)  │
└──────────────┘                    └──────────────┘

如果计算单元等数据:Memory-bound(带宽瓶颈)
如果数据等计算完成:Compute-bound(算力瓶颈)

关键指标:算术强度 (Arithmetic Intensity)

算术强度 = FLOPs / Bytes accessed
         = 做了多少计算 / 搬了多少数据
  • 算术强度高 → Compute-bound(计算密集,GPU 算力是瓶颈)
  • 算术强度低 → Memory-bound(访存密集,显存带宽是瓶颈)

2. Prefill 阶段:Compute-bound

2.1 为什么是算力瓶颈?

Prefill 一次性处理整个 prompt(可能几百到几千个 token),核心操作是大矩阵乘法:

输入: X [batch, seq_len, hidden_dim]    如 [1, 2048, 4096]
权重: W [hidden_dim, hidden_dim]         如 [4096, 4096]
输出: Y = X · W  [1, 2048, 4096]

FLOPs ≈ 2 × batch × seq_len × hidden² = 2 × 1 × 2048 × 4096² ≈ 68.7 GFLOPs
Bytes = 权重读取 = 4096 × 4096 × 2 = 33.5 MB

算术强度 = 68.7G / 33.5M ≈ 2048  ← 非常高!

seq_len 越大,算术强度越高,越是 compute-bound。GPU 的 TFLOPS 决定了 prefill 速度。

2.2 Prefill 的性能特征

Prefill 性能 ≈ 模型 FLOPs / GPU TFLOPS

例:Llama-3-8B prefill 2048 tokens
总 FLOPs ≈ 2 × 8B × 2048 ≈ 32.8 TFLOPs
A100 (312 TFLOPS FP16) → 理论时间 ≈ 32.8/312 ≈ 105ms
H100 (990 TFLOPS FP16) → 理论时间 ≈ 32.8/990 ≈ 33ms

关键洞察:

  • 提高 batch size 对 prefill 友好(矩阵更大,GPU 利用率更高)
  • 更强的 GPU(更高 TFLOPS)直接加速 prefill
  • FlashAttention 通过减少 HBM 访问来优化 prefill 中的 attention 计算

3. Decode 阶段:Memory-bound

3.1 为什么是带宽瓶颈?

Decode 每次只处理 1 个 token,核心操作变成了矩阵-向量乘法:

输入: x [batch, 1, hidden_dim]          如 [1, 1, 4096]
权重: W [hidden_dim, hidden_dim]         如 [4096, 4096]  ← 权重没变!
输出: y = x · W  [1, 1, 4096]

FLOPs ≈ 2 × 1 × 1 × 4096² ≈ 33.5 MFLOPs
Bytes = 权重读取 = 4096 × 4096 × 2 = 33.5 MB

算术强度 = 33.5M / 33.5M ≈ 1  ← 极低!

每读 1 byte 数据只做 1 次运算,GPU 的计算单元大部分时间在等数据。

3.2 Decode 的性能特征

Decode 每 token 延迟 ≈ 模型参数量 × bytes_per_param / GPU 带宽

例:Llama-3-8B decode (FP16)
数据量 = 8B × 2 bytes = 16 GB(每步都要读一遍所有权重)
A100 带宽 = 2 TB/s → 理论时间 ≈ 16/2000 ≈ 8ms/token → ~125 tokens/s
H100 带宽 = 3.35 TB/s → 理论时间 ≈ 16/3350 ≈ 4.8ms/token → ~208 tokens/s

关键洞察:

  • 显存带宽比算力更影响生成速度
  • 单请求 decode 时 GPU 计算利用率极低(可能 <5%)
  • 增大 batch 可以提高利用率(同一份权重服务多个请求)
  • 量化(FP16→INT8→INT4)直接减少要读的数据量,加速 decode

3.3 为什么 Decode 怎么优化都快不太多?

单请求 decode 的理论下限 = 模型大小 / 显存带宽

这是物理限制:
- 每生成 1 个 token,必须读一遍所有模型权重
- 读取速度受限于 HBM 带宽
- 除非减小模型(量化)或增加带宽(更好的硬件),否则无法突破

A100:  8B FP16 → 最快 ~8ms/token
H100:  8B FP16 → 最快 ~4.8ms/token
H100:  8B INT4 → 最快 ~1.2ms/token  ← 量化 4 倍,速度提 4 倍

4. Roofline 模型:可视化性能瓶颈

Roofline 模型是分析 GPU 程序性能的经典工具:

性能 (FLOPS)

    │         ╱ ← 带宽上限斜线 (Memory-bound 区域)
    │        ╱
    │       ╱
    │      ╱─────────────── ← 算力上限 (Compute-bound 区域)
    │     ╱
    │    ╱
    │   ╱
    │  ╱
    │ ╱
    │╱
    └──────────────────────── 算术强度 (FLOPs/Byte)

         拐点 = Peak FLOPS / Peak BW
A100 拐点 = 312 TFLOPS / 2 TB/s = 156 FLOPs/Byte

算术强度 < 156 → Memory-bound(decode 阶段,AI ≈ 1)
算术强度 > 156 → Compute-bound(prefill 阶段,AI ≈ 2048)

5. 实际影响:为什么这些知识很重要?

5.1 硬件选型

场景瓶颈选卡策略
长 prompt prefillCompute-bound选高 TFLOPS(H100 > A100)
实时对话 decodeMemory-bound选高带宽(HBM3 > HBM2e)
高并发服务两者都有需要平衡 TFLOPS 和带宽

5.2 优化策略映射

优化技术主要加速阶段原理
FlashAttentionPrefill减少 HBM 访问,在 SRAM 中完成 attention
量化 (INT8/INT4)Decode 为主减少权重数据量,降低带宽需求
增大 batchDecode 为主同一份权重服务多请求,提高算术强度
Tensor Parallelism两者多卡分摊计算和带宽
Speculative DecodingDecode用小模型猜测,大模型批量验证
KV Cache 量化Decode减少 KV 读取的数据量

5.3 Batch Size 对两阶段的不同影响

Prefill (seq_len=2048):
  batch=1:  算术强度 ≈ 2048  → Compute-bound ✓
  batch=32: 算术强度 ≈ 2048  → 还是 Compute-bound(seq_len 已经够大)
  → batch 增大主要增加总吞吐量

Decode (seq_len=1):
  batch=1:  算术强度 ≈ 1     → Memory-bound ✗
  batch=32: 算术强度 ≈ 32    → 还是 Memory-bound,但好多了
  batch=256:算术强度 ≈ 256   → 接近拐点,GPU 利用率大幅提升
  → batch 增大是 decode 阶段最有效的优化手段之一

这就是为什么推理服务(vLLM/TGI)都在拼命做 batching。


6. 关键要点总结

┌──────────────────────────────────────────────────────────┐
│  Compute vs Memory Bound 核心认知                          │
├──────────────────────────────────────────────────────────┤
│  1. Prefill = 大矩阵乘 = Compute-bound = 看 TFLOPS        │
│  2. Decode = 矩阵向量乘 = Memory-bound = 看 HBM 带宽      │
│  3. 算术强度 = FLOPs/Bytes,决定瓶颈在哪                    │
│  4. Decode 的理论下限 = 模型大小 / 显存带宽                  │
│  5. 增大 batch 是提升 decode GPU 利用率的关键                │
│  6. 量化通过减少数据量直接加速 memory-bound 的 decode        │
└──────────────────────────────────────────────────────────┘

7. 延伸阅读

修改历史1 次提交