1. 显存基础:GPU显存架构与核心概念

做GPU优化这些年,我见过太多人一上来就调kernel、改算法,结果性能瓶颈其实卡在显存上。说白了,你不了解显存怎么工作的,优化就是瞎忙活。这一章,咱们把显存的老底翻一翻。

1.1 HBM vs GDDR:两种主流显存架构

目前GPU用的显存,主要就两派:HBM(高带宽显存)和GDDR(图形双倍数据率显存)。

HBM 的特点是堆叠。把多个DRAM die垂直堆在一起,通过硅中介层连到GPU核心。这样做的好处是位宽极宽——HBM2e能做到1024位甚至更宽。我最早接触HBM是在NVIDIA的V100上,当时第一反应是:这带宽也太离谱了。

GDDR 则是传统路线。颗粒分布在GPU周围,走PCB走线。GDDR6X甚至用上了PAM4信号编码,单颗颗粒带宽很高,但位宽受限(通常384位或512位)。

核心区别一句话:HBM靠堆叠和宽位宽取胜,GDDR靠高频和成熟工艺压低成本。

我个人的习惯是:做推理部署用GDDR(便宜、够用),做大模型训练必须上HBM(带宽就是命)。

1.2 显存带宽与延迟:你写的每一行代码都在跟它们打交道

显存带宽 = 频率 × 位宽 × 每周期传输次数。公式很简单,但实际影响很复杂。

架构 典型带宽 延迟(ns) 适用场景
HBM2e ~2 TB/s ~120 大模型训练、科学计算
GDDR6 ~600 GB/s ~100 游戏、中小模型推理
GDDR6X ~1 TB/s ~110 高端消费卡、部分训练

你可能会问:为什么HBM带宽更高,延迟反而更大?嗯,这是因为HBM经过硅中介层和堆叠结构,路径更长。但实际工作中,带宽瓶颈远比延迟瓶颈常见。我曾经优化过一个推荐系统模型,把数据布局从AoS改成SoA,吞吐直接翻倍——原因就是更好地利用了显存带宽。

避坑指南:我曾经以为只要计算密集就没事,结果发现访存模式不对,SM(流多处理器)大部分时间在等数据。记住:GPU是吞吐优先的设备,延迟靠大量并行来隐藏。

1.3 显存容量与计算单元的关系

显存容量决定了你能装多大的模型,计算单元(SM、CUDA Core、Tensor Core)决定了你算得有多快。两者必须匹配。

举个例子:A100有80GB显存,6912个CUDA Core。如果你跑一个70B参数的大模型,光参数就要140GB(FP16),单卡根本放不下。这时候要么模型并行,要么量化。

我见过最典型的翻车案例:有人买了块RTX 3090(24GB显存),想跑LLaMA-65B。结果模型加载到一半就OOM了。嗯,显存容量不够,再强的计算单元也白搭。

反过来,显存太大但计算单元弱也不行。比如某些云端实例配了超大显存但SM数量少,跑小batch size还行,一上大batch就卡在计算上。

注意:显存容量和计算单元的比例,直接影响你的batch size选择。我个人建议:训练时让显存占用在80%-90%之间,留点余量给临时变量和碎片。

1.4 显存层次结构:从寄存器到全局显存

GPU的显存不是铁板一块,它有清晰的层次结构。你想想看,从最快到最慢:

  • 寄存器:每个线程私有,零延迟,但数量极少(每个SM几千个)
  • 共享内存:同一个block内共享,延迟极低(~20周期),容量有限(通常48-96KB per SM)
  • L1/L2缓存:自动管理,L1延迟~30周期,L2延迟~200周期
  • 全局显存:所有线程可访问,延迟最高(~400-800周期),但容量最大

我刚开始写CUDA时,总喜欢把所有数据放全局显存,觉得省事。结果性能惨不忍睹。后来学乖了:能放共享内存的绝不放全局,能用寄存器的绝不放共享。

一个简单的经验法则:如果某个数据被同一个block内的线程反复读取,就把它搬进共享内存。如果只被单个线程用,尽量用寄存器。

1.5 知识体系总览

下面这张图,把显存的核心知识点串起来了。我建议你保存下来,后面每学一章都回来对照一下。

GPU显存知识体系 显存架构 HBM(堆叠+宽位宽) GDDR(高频+成熟工艺) 性能指标 带宽 = 频率 × 位宽 延迟(HBM略高) 容量 vs 计算单元匹配 层次结构 寄存器(最快,最小) 共享内存(低延迟) L1/L2缓存(自动管理) 全局显存(最慢,最大) 核心原则:理解架构 → 匹配带宽 → 善用层次 → 平衡容量与算力 优化方向:减少全局访问 → 提高局部性 → 隐藏延迟 最终目标:让计算单元永远不空等数据

这张图把显存知识分成三大块:架构、性能指标、层次结构。底部是核心原则和优化方向。你每次做显存优化时,都可以回来看看自己卡在哪一层。

个人经验:我每次接手一个新模型,第一件事就是跑一遍带宽测试和延迟测试。搞清楚显存的底细,后面优化才有方向。别一上来就调kernel,先看看数据是怎么在显存里流动的。

好了,显存基础就聊到这儿。记住:显存不是无限大的,也不是无限快的。你写的每一行CUDA代码,最终都要跟这些物理限制打交道。理解它们,你才能写出真正高效的GPU程序。

可可精品资料库