第二章:硬件基础与计算模型:GPU架构概览(SM、Warp、Memory Hierarchy)、CPU与GPU的协同

好,咱们正式开始聊硬件。很多做算子优化的朋友,上来就怼代码,调参数,结果性能死活上不去。为什么?说白了,你不了解你的对手——GPU。你连它内部怎么工作的都不知道,怎么让它听你的话?

我个人习惯,在动手写任何一行CUDA代码之前,先花半小时把目标GPU的架构文档翻一遍。这不是浪费时间,这是磨刀不误砍柴工。今天我就带你把这把刀磨快。

2.1 GPU的核心:SM(流多处理器)

GPU不是一个大铁块。它是由很多个SM组成的。你可以把SM想象成一个微型计算机,有自己的处理器、缓存、调度器。一个GPU有多少个SM,基本决定了它的算力上限。

我在项目中遇到过一个问题:一个kernel在A100上跑得飞快,换到V100上就慢了一半。查了半天,发现是SM数量减半了,但线程块数量没调。嗯,这就是没摸清家底的结果。

每个SM内部包含:

  • CUDA核心:执行整数和浮点运算。别被名字骗了,它不是独立的CPU核心,更像是一个高度精简的ALU。
  • 共享内存:极低延迟,但容量有限。这是算子优化的兵家必争之地。
  • 寄存器文件:每个线程私有的最快存储。但总量固定,线程多了,每个线程分到的就少了。
  • Warp调度器:负责把指令发给线程束执行。这个后面细说。

核心观点:SM是并行执行的基本单元。你的优化策略,本质上就是在跟SM的硬件资源做博弈。

2.2 Warp:真正的执行单元

你写代码时觉得是线程在并行跑。其实不是。GPU真正的执行单位是Warp——一个由32个线程组成的集合。这32个线程在SM里是同步执行同一条指令的。

为什么会这样?你想想看,如果每个线程都独立取指令、译码、执行,那光指令调度单元就得占多大面积?GPU把32个线程绑在一起,共享一套指令单元,面积省下来了,算力上去了。代价就是——分支发散。

我曾经在一个项目里,写了个if-else判断,32个线程里一半走if,一半走else。结果呢?性能直接腰斩。因为Warp里的线程必须串行执行不同的分支路径。这就是分支发散,是性能杀手。

避坑指南:我曾经在写Reduce算子时,让每个Warp内的线程根据线程ID做不同的操作。结果性能惨不忍睹。后来改成让整个Warp做同一件事,用Shuffle指令内部通信,速度直接翻倍。记住:让Warp内的线程保持统一行动。

2.3 Memory Hierarchy:存储层次与带宽博弈

GPU的存储层次,说白了就是一个金字塔。越往上越快,但越小越贵。越往下越慢,但越大越便宜。优化算子的本质,就是尽量把数据往金字塔顶端塞。

存储层级 延迟(大约) 容量 作用域
寄存器 ~1 cycle 每个线程最多255个 线程私有
共享内存 ~5-30 cycles 每个SM 48-164 KB 线程块内共享
L1缓存 ~30-80 cycles 每个SM 128-192 KB SM内共享
L2缓存 ~200-400 cycles 芯片级 40-80 MB 全局共享
全局内存 ~400-800 cycles 显存 16-80 GB 所有线程

看到这个延迟差距了吗?从全局内存读一次数据,够你在寄存器里算400次加法。所以,减少全局内存访问是优化的第一要义。

我个人的经验是:如果一个kernel的瓶颈在访存,那优化共享内存的使用往往立竿见影。但如果瓶颈在计算,那就要考虑指令级并行或者增加Warp数量来隐藏延迟。

2.4 CPU与GPU的协同:异构计算的正确姿势

CPU和GPU不是竞争关系,是合作关系。CPU擅长控制流和复杂逻辑,GPU擅长大规模并行计算。正确的做法是:CPU当指挥官,GPU当苦力。

具体来说:

  1. 数据传输:CPU负责把数据从内存搬到显存,再从显存搬回来。这个开销很大,要尽量减少传输次数。
  2. 任务调度:CPU启动kernel,然后可以去做别的事。GPU异步执行。用cudaStream可以实现流水线。
  3. 错误处理:GPU出错了,CPU要能捕获并处理。别让GPU默默吞掉错误。

注意:我曾经犯过一个低级错误——在CPU和GPU之间来回传输小数据。每次传输都有微秒级的延迟,累积起来就是灾难。后来我改用固定内存(Pinned Memory)和异步传输,性能提升了一个数量级。记住:批量传输,避免小数据频繁搬运。

还有一个容易被忽略的点:CPU和GPU的同步。你启动一个kernel后,CPU默认不会等它执行完。如果你紧接着就要用结果,必须显式同步。但同步会阻塞CPU,浪费计算资源。我建议用cudaEvent来做细粒度的同步,只在真正需要结果的地方等待。

2.5 知识体系总览

下面这张图,是我自己总结的GPU架构知识体系。每次做优化前,我都会对照着看一遍,确认自己没漏掉什么。

GPU架构与计算模型知识体系 GPU架构概览 SM(流多处理器) Warp(线程束) Memory Hierarchy CPU-GPU协同 CUDA核心 共享内存 寄存器文件 32线程同步 分支发散 寄存器 共享内存 L1/L2缓存 全局内存 数据传输 异步执行 同步机制 流水线 核心:理解硬件约束,才能写出高效的算子

这张图把今天讲的内容串起来了。你每次做优化时,都可以对照着看看:我是在优化SM利用率?还是在减少Warp发散?还是在降低访存延迟?还是在改善CPU-GPU通信?

好了,硬件基础就聊到这儿。记住一句话:不懂硬件的优化,都是瞎优化。下一章我们开始动手写代码,但今天这些概念,会一直贯穿整个课程。

可可精品资料库