显存基础:GPU 显存层次结构、显存带宽、显存容量与性能关系
在深入 TensorRT-LLM 的显存优化技巧之前,必须先建立对 GPU 显存系统的底层认知。许多优化策略——如 KV Cache 量化、PagedAttention、算子融合——本质上都是在与显存的物理特性“博弈”。本节将拆解显存的层次结构、带宽瓶颈以及容量与性能之间的非线性关系,为后续章节提供理论基石。
3.1 显存层次结构:从寄存器到全局内存
GPU 的显存并非单一均匀的存储池,而是一个具有明显速度梯度的层次化体系。以 NVIDIA A100/H100 为例,从内到外依次为:
- 寄存器文件(Register File):每个 SM 内部分布,容量极小(A100 每个 SM 为 256KB),但访问延迟仅约 1 个时钟周期。这是最快的存储,但完全由编译器分配,开发者无法直接控制。
- 共享内存(Shared Memory):每个 SM 可配置 164KB(A100),延迟约 20-30 周期。它相当于一个由开发者显式管理的片上缓存,是 TensorRT-LLM 中融合算子(如 FlashAttention)的关键加速手段。
- L1 缓存 / 纹理缓存:与共享内存在物理上共用同一块 SRAM,可动态划分。用于缓存全局内存的局部访问。
- L2 缓存:A100 为 40MB,H100 为 50MB。所有 SM 共享,延迟约 200 周期。对于大模型推理,L2 命中率直接影响 KV Cache 访问效率。
- 全局内存(显存 VRAM):即 HBM2e/HBM3 显存,容量最大(40/80GB),但延迟高达 400-800 周期,带宽也远低于片上存储。
3.2 显存带宽:LLM 推理的硬约束
大语言模型推理(尤其是 decode 阶段)是典型的 memory-bound 任务。当 batch size 较小或使用贪婪解码时,每个 token 的生成仅需计算一次矩阵向量乘,此时算力利用率极低,瓶颈完全在于从显存中读取模型权重和 KV Cache 的速度。
以 LLaMA-7B 为例,模型权重约 14GB(FP16)。在 A100 上,理论算力为 312 TFLOPS,而显存带宽仅 1.5TB/s。若采用 batch size = 1 的 decode,每个 token 需要读取全部 14GB 权重,耗时约 14GB / 1.5TB/s ≈ 9.3ms。而实际计算量仅约 2×7B×1 = 14 GFLOPs,在 312 TFLOPS 下仅需 0.045ms。这意味着 GPU 算力利用率不足 0.5%。
--max_batch_size 参数并非越大越好。当 batch size 增大到一定程度(如 32-64),计算量线性增长而权重读取量不变,算力利用率才会显著提升。但 batch 增大会导致 KV Cache 内存占用线性膨胀,因此需要权衡。
3.3 显存容量:决定模型能否部署的硬边界
显存容量决定了模型权重、KV Cache、激活值、CUDA context 等能否同时驻留。对于 TensorRT-LLM 推理,显存占用可分解为以下公式:
总显存占用 ≈ 模型权重 + KV Cache + 激活值 + CUDA context + 临时缓冲区
其中:
KV Cache = 2 (K和V) × num_layers × num_heads × head_dim × seq_len × batch_size × 精度字节数
激活值 = 与 batch_size × seq_len × hidden_size 成正比(通常 < 1GB)
以 LLaMA-13B(40 层,40 头,head_dim=128,FP16)为例,单条序列的 KV Cache 占用为:
2 × 40 × 40 × 128 × 2048 × 1 × 2B = 1.34 GB(seq_len=2048, batch=1)
若 batch=16, seq_len=4096,则 KV Cache = 2×40×40×128×4096×16×2B ≈ 42.9 GB
可见,KV Cache 随 batch 和序列长度线性增长,在长序列、大 batch 场景下甚至可能超过模型权重本身。TensorRT-LLM 的 PagedAttention 机制正是为了消除 KV Cache 的碎片化浪费,实现按需分配。
3.4 容量与性能的非线性关系:临界点效应
显存容量与推理性能并非简单的线性关系,而是存在明显的 临界点效应。当总占用接近显存上限时,性能会急剧恶化,原因包括:
- 内存碎片化:频繁的分配/释放导致可用显存碎片化,即使总空闲空间足够,也可能无法分配连续大块内存。
- 换页/溢出:一旦超出显存,TensorRT-LLM 会尝试将部分 KV Cache 换出到 CPU 内存(若启用),导致 PCIe 传输延迟(约 10-20GB/s,比显存慢 100 倍)。
- L2 命中率下降:当 KV Cache 占用过大,L2 缓存的有效命中率降低,更多请求直接访问 HBM,实际带宽下降。
| 显存占用率 | 实际带宽利用率 | 典型现象 |
|---|---|---|
| < 60% | 85-95% | 性能稳定,L2 命中率较高 |
| 60% - 85% | 70-85% | 碎片化开始出现,偶发延迟尖峰 |
| 85% - 95% | 50-70% | 频繁内存整理,吞吐明显下降 |
| > 95% | < 50% | 可能触发 OOM 或 CPU offload,延迟剧增 |
3.5 案例:为什么 80GB 显存跑不动 70B 模型?
以 LLaMA-70B 为例,FP16 权重即需 140GB,显然无法单卡部署。即使采用 INT4 量化(权重降至 35GB),在 80GB 的 H100 上仍面临挑战:
- 权重:35GB(INT4 量化后)
- CUDA context + 激活值:约 2-3GB
- 剩余可用:约 42GB
- 若 batch=1, seq_len=2048,KV Cache 约 2×80×8×128×2048×1×2B ≈ 0.67GB(80 层,8 头,head_dim=128)
表面看 42GB 远大于 0.67GB,似乎可以运行。但实际推理时,TensorRT-LLM 需要预留 临时缓冲区(用于 beam search、采样、中间结果),通常需要额外 4-8GB。更关键的是,显存分配器的最小分配单元(通常为 512MB 或 1GB)会导致大量内部碎片。最终可用 KV Cache 空间可能仅剩 30GB 左右,若用户请求的 max_seq_len 较大(如 8192),KV Cache 需求将增长 4 倍至 2.7GB,虽然仍可容纳,但 L2 命中率已大幅下降。
nvidia-smi --query-gpu=memory.used --format=csv -l 1 监控峰值,并预留至少 10-15% 的显存余量。
3.6 复盘:显存优化的三个核心原则
基于上述物理特性,TensorRT-LLM 的显存优化可归纳为以下原则:
- 减少权重读取量:通过 INT8/INT4 量化、稀疏化、蒸馏,降低每次 decode 需要从 HBM 读取的字节数。这是最直接的带宽优化。
- 提高数据复用率:增大 batch size、使用 continuous batching,让同一份权重被更多请求复用,摊薄带宽成本。
- 管理 KV Cache 生命周期:使用 PagedAttention 消除碎片,结合
--kv_cache_free_gpu_memory_fraction参数控制预留比例,避免临界点效应。