GPU架构基础:SM、Warp、Thread Block、Global Memory、Shared Memory
各位同学,今天我们来聊聊GPU的骨架。说白了,你要写好CUDA核函数,就得先摸清楚GPU到底是怎么干活的。我刚开始接触CUDA时,也踩过不少坑——比如以为线程越多越快,结果跑起来比CPU还慢。后来才明白,不理解硬件架构,写出来的代码就是瞎蒙。
SM:GPU的心脏
SM(Streaming Multiprocessor)是GPU最核心的计算单元。你可以把它想象成一个微型处理器,里面有自己的寄存器、计算单元、缓存和调度器。一块GPU上通常有几十到上百个SM。
我在项目中遇到过一个问题:同一个核函数,在RTX 3090上跑得飞快,换到A100上反而慢了。后来一查,原来是SM数量不同导致的资源分配策略差异。嗯,这里要注意——SM的数量决定了你的并行度上限。
关键点:每个SM能同时驻留的线程块数量是有限的,通常为16-32个。别想着把几千个线程块全塞进去,硬件吃不消。
Warp:真正的执行单元
Warp是GPU调度和执行的基本单位。一个Warp包含32个线程,它们在同一时刻执行同一条指令。你想想看,这就像32个人排成一排,教官喊「向左转」,所有人必须同时向左转。
为什么会这样?因为GPU的设计哲学就是「单指令多线程」(SIMT)。32个线程共享一个指令单元,这样能省下大量的控制逻辑,把晶体管用在计算上。
个人经验:我建议你在写核函数时,尽量让同一个Warp里的线程走相同的分支。如果出现分支发散(比如if-else),性能会大打折扣。我曾经在一个图像处理项目里,因为没注意分支发散,性能直接掉了40%。
Thread Block:组织线程的容器
Thread Block(线程块)是程序员直接控制的线程组织方式。一个Block里的线程可以协作,共享数据,还能同步。Block的大小通常设为128、256或512个线程。
这里有个坑:Block的大小必须是32的倍数。为什么?因为Warp是32个线程一组,Block大小不是32的倍数,就会有空闲的线程,浪费计算资源。
| Block大小 | Warp数量 | 资源利用率 |
|---|---|---|
| 128 | 4 | 100% |
| 256 | 8 | 100% |
| 300 | 10(有浪费) | 93.75% |
避坑指南:我曾经在写矩阵乘法时,把Block大小设成了100。结果每个Block有4个线程闲置,整体性能比用128的版本慢了15%。从那以后,我再也不用非32倍数的Block大小了。
Global Memory:大而慢的仓库
Global Memory就是GPU的显存,容量大(几GB到几十GB),但访问延迟高(几百个时钟周期)。所有线程都能读写它,但速度嘛...说实话,挺慢的。
优化Global Memory访问的关键是合并访问。什么意思?就是让同一个Warp里的32个线程,访问连续的内存地址。这样GPU可以把多次内存访问合并成一次,效率翻倍。
核心原则:尽量让线程ID和内存地址一一对应。比如线程0访问地址0,线程1访问地址1,以此类推。别让线程0访问地址0,线程1访问地址100,那样就乱套了。
Shared Memory:小而快的缓存
Shared Memory是每个SM内部的高速缓存,容量很小(通常几十KB),但访问速度极快(几个时钟周期)。同一个Block里的线程可以共享这块内存。
我建议你在需要频繁数据复用的场景下,优先使用Shared Memory。比如矩阵乘法、卷积、归约等操作,把数据从Global Memory搬到Shared Memory里,然后反复使用,能省下大量的全局内存访问。
个人技巧:使用Shared Memory时要注意Bank Conflict。Shared Memory被分成32个Bank,如果多个线程同时访问同一个Bank,就会发生冲突,导致串行化。解决办法是让线程访问的地址错开,比如加个步长或者填充一些无用数据。
知识体系总览
下面这张图展示了GPU架构的核心概念和它们之间的关系。我画这张图时,特意把层次关系理清楚了——从硬件到软件,从大到小。
从这张图可以看出,GPU的层次结构非常清晰:
- 最底层是Global Memory,所有SM共享,容量大但速度慢
- 中间层是SM,每个SM有自己的Shared Memory、Warp调度器和寄存器
- 最上层是Thread Block,它被分配到某个SM上执行,Block内的线程共享Shared Memory
总结一下
理解这五个概念,你就掌握了GPU编程的底层逻辑。说白了,写CUDA代码就是在做资源管理——怎么分配线程块,怎么利用Shared Memory,怎么让Global Memory访问更高效。我见过太多人一上来就写核函数,结果性能惨不忍睹。嗯,先打好基础,后面优化起来才顺手。
一句话记住:SM是工厂,Warp是流水线,Thread Block是工单,Global Memory是仓库,Shared Memory是工作台。你作为工程师,就是要把工单安排得明明白白,让流水线不空转,让工作台不闲置。
想要更多资料,联系可可