1. 显存基础与压测概述

大家好,我是你们这堂课的主讲。做了这么多年GPU性能优化,我最大的感触就是——显存这东西,看着简单,用起来全是坑。今天咱们就从最基础的开始聊,把显存的底裤扒干净。

1.1 GPU显存架构:HBM vs GDDR

先说说显存类型。目前主流就两种:HBM(高带宽显存)和GDDR(图形双倍数据率显存)。

HBM,说白了就是堆叠起来的。像盖楼一样,把多个DRAM die堆在一起,中间用TSV(硅通孔)连接。这样做的好处是——带宽极高,功耗还低。我最早接触HBM是在NVIDIA的P100上,当时看到那带宽数据,说实话,惊到了。

GDDR呢,就是传统的平铺设计。芯片和显存颗粒分布在PCB上,走线长,延迟相对高一些。但胜在容量大、成本低。RTX 3090用的就是GDDR6X,24GB,打游戏爽,做训练也够用。

来,我画个图帮你们理解:

HBM 架构(高带宽显存) Logic Die(逻辑层) HBM Die 1 HBM Die 2 HBM Die 3 TSV 硅通孔连接 GDDR 架构(传统显存) GPU 核心芯片 GDDR 颗粒1 GDDR 颗粒2 GDDR 颗粒3 GDDR 颗粒4 HBM:高带宽(~2TB/s)、低功耗、容量小 GDDR:容量大(~24GB)、成本低、延迟稍高

核心区别一句话总结:HBM是带宽怪兽,适合计算密集型;GDDR是容量担当,适合数据密集型。

1.2 显存带宽与延迟

带宽和延迟,这两个参数决定了你的模型能跑多快。

带宽,就是单位时间内能读写多少数据。公式很简单:

带宽 = 显存频率 × 位宽 × 2(DDR双倍速率)

举个例子:A100的HBM2e,频率1215 MHz,位宽5120 bit,算下来:

1215 MHz × 5120 bit × 2 = 12.44 Gbps × 5120 bit = 约 1.6 TB/s

嗯,这个数字很漂亮。但实际用的时候,你几乎跑不到这个理论值。为什么?因为还有延迟。

延迟,就是从发出请求到拿到数据的时间。HBM的延迟大概在100-200纳秒,GDDR稍微好一点,80-150纳秒。你想想看,GPU核心一个时钟周期才0.5纳秒,等一次显存访问要等几百个周期——这差距,够CPU执行上千条指令了。

显存类型 典型带宽 典型延迟 常见于
HBM2e 1.6 - 2.0 TB/s 100 - 200 ns A100, MI250
HBM3 3.0 - 3.5 TB/s 80 - 150 ns H100, B200
GDDR6 500 - 700 GB/s 80 - 120 ns RTX 3080, A4000
GDDR6X 800 - 1000 GB/s 70 - 100 ns RTX 3090, RTX 4090

我的经验:做压测时,别只看带宽。我曾经遇到一个场景,带宽利用率只有40%,但延迟已经飙到300ns了。后来发现是显存访问模式太随机,导致缓存命中率极低。说白了,带宽是上限,延迟才是日常。

1.3 吞吐压测的目标与指标

吞吐压测,说白了就是看你的系统能扛多大并发。两个核心指标:

  • QPS(Queries Per Second):每秒能处理多少个查询请求。适合搜索、推荐这类场景。
  • TPS(Transactions Per Second):每秒能完成多少个完整事务。适合交易、计费这类场景。

我个人习惯把QPS和TPS统称为「吞吐量」。但要注意,这两个指标不能混用。你想想看,一个搜索请求可能只查一次显存,但一个交易事务可能要读写十几次显存——同样的QPS和TPS,对显存的压力天差地别。

压测的核心公式:

吞吐量 = 并发数 / 平均延迟

这个公式看着简单,但实际压测时,并发数一上去,延迟就会飙升。为什么?因为显存带宽是共享的,大家都在抢。

1.4 显存瓶颈识别

怎么判断你的系统是不是卡在显存上?我教你们几个土办法:

  1. 看带宽利用率:用nvidia-smi或者Nsight Systems,如果带宽利用率超过80%,基本就是显存瓶颈了。
  2. 看延迟分布:如果大部分请求的延迟都集中在显存访问阶段,而不是计算阶段,那问题就在显存。
  3. 看缓存命中率:L1/L2缓存命中率低于50%的话,说明数据局部性很差,显存压力会很大。

我曾经踩过的坑:有一次压测,QPS死活上不去,我盯着带宽利用率看了半天,才60%。后来用Nsight一分析,发现是显存分配和释放太频繁,导致大量时间花在cudaMalloc/cudaFree上。嗯,从那以后,我养成了「显存复用」的习惯——提前分配好,压测过程中不释放。

最后,给你们看一个典型的显存瓶颈识别流程:

# 用nvidia-smi监控显存
nvidia-smi --query-gpu=memory.used,memory.total,utilization.memory --format=csv -l 1

# 用Nsight Systems做profiling
nsys profile --stats=true ./your_benchmark

# 重点关注:
# - Memory Throughput(显存吞吐)
# - Memcpy Bandwidth(拷贝带宽)
# - Kernel Launch Overhead(内核启动开销)

好了,这一章的基础就到这里。显存这东西,你越了解它,越知道怎么「骗」它——让数据尽量留在缓存里,让访问尽量连续,让分配尽量提前。后面的章节,咱们会一步步把这些技巧拆开来讲。

一句话记住:显存不是无限的,带宽不是无限的,但你的优化思路可以是无限的。