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 知识体系总览
下面这张图,把显存的核心知识点串起来了。我建议你保存下来,后面每学一章都回来对照一下。
这张图把显存知识分成三大块:架构、性能指标、层次结构。底部是核心原则和优化方向。你每次做显存优化时,都可以回来看看自己卡在哪一层。
个人经验:我每次接手一个新模型,第一件事就是跑一遍带宽测试和延迟测试。搞清楚显存的底细,后面优化才有方向。别一上来就调kernel,先看看数据是怎么在显存里流动的。
好了,显存基础就聊到这儿。记住:显存不是无限大的,也不是无限快的。你写的每一行CUDA代码,最终都要跟这些物理限制打交道。理解它们,你才能写出真正高效的GPU程序。