GPU深解笔记:核心组件与内存层次

127 阅读7分钟

GPU计算核心

GPU的计算能力不是由“单个核心”决定的,而是“核心集群(SM)+专用加速单元”的协同。

流多处理器SM

SM是GPU的“最小独立计算单元”,相当于CPU的“核心”,但功能更复杂。一个GPU芯片由数十个SM组成,每个SM内部集成了“计算单元(CUDA Core/Tensor Core)、存储单元(寄存器/共享内存)、调度单元”三大模块。

  • SM是资源分配和调度的基本单位,当用CUDA写kernel时,GPU会把kernel的线程块(Block)分配到某个SM上进行,SM再负责调度块内的线程。

SM内通用计算单元CUDA Core

CUDA Core是SM内执行“通用浮点/整数计算”的最小单元,对应CPU的ALU。

  • 核心关系:每个SM包含数十到数百个CUDA Core,线程数大于CUDA Core数,一个SM可能同时管理数万个线程,但CUDA Core只有数十个,这需要靠调度让Core不空闲。
  • 局限性:CUDA Core擅长“单指令单数据(SIMD)”的并行计算,但面对AI中大量的“矩阵乘法(GEMM)”时,效率很低,因为矩阵运算需要“单指令多数据(SIMD)”的并行,这就需要Tensor Core。

SM内AI专用加速单元Tensor Core

Tensor Core是英伟达为AI workload(尤其是深度学习的矩阵运算)设计的专用硬件加速单元,是GPU跑模型的“性能核心”(没有Tensor Core,GPU跑大模型会慢10倍以上)。

  • 核心能力:专门执行“混合精度矩阵乘法-累加(FMA)”
  • AI Infra的关键:所有深度学习框架的矩阵运算,最终都会调用Tensor Core;模型量化(如FP8)、混合精度训练,本质都是为了适配Tensor Core的精度要求,最大化其利用率。

GPU内存层次结构

AI workload的性能杀手往往不是计算,而是内存访问——如果数据不能快速传到计算单元,再强的算力也会空转。GPU的内存层次设计,就是为了“用不同速度/容量的内存,匹配不同访问需求”,而共享内存是并行优化的核心。

内存类型位置速度(延迟)容量(单 SM/A100)访问规则核心作用
寄存器(Register)SM 内,线程私有~1-2 ns(最快)单 SM 256KB-512KB每个线程私有,线程结束后数据销毁存储线程执行时的临时变量(如kernel中的局部变量),避免频繁访问慢内存
共享内存(Shared Memory)SM 内,线程块共享~10-20 ns单 SM 64KB-128KB同一线程块(Block)的所有线程可访问,需手动管理并行优化核心:将全局内存的重复数据缓存到这里,减少全局内存访问(比如矩阵分块计算时的块数据)
L1 缓存SM 内,硬件自动管理~20-30 ns单 SM 192KB硬件自动缓存全局内存 / 常量内存的访问,无需手动干预辅助共享内存,减少对 L2 缓存的访问
L2 缓存GPU 芯片级,所有 SM 共享~100-200 nsA100 总计 40MB所有 SM 共享,硬件自动管理作为全局内存和 SM 之间的 “桥梁”,缓存多个 SM 的常用数据
全局内存(Global Memory)GPU 外部(显存,如 HBM2)~400-800 ns(最慢)A100 总计 40GB-80GB所有线程可访问,需通过 PCIe 或 NVLink 传输存储模型权重、训练数据等 “海量数据”,但访问成本极高
常量内存(Constant Memory)GPU 芯片级,只读~50-100 ns总计 64KB所有线程只读,硬件自动缓存存储训练中的常量(如模型的固定参数)

关键结论:内存优化的核心逻辑

  1. 速度差决定优化方向:全局内存速度(缓慢程度)是共享内存的20-40倍,是寄存器的200-400倍——优化的本质就是“尽量让计算单元访问快内存,减少全局内存访问”
  2. 容器限制决定线程数:寄存器和共享内存是SM内的“稀缺资源”——每个SM的寄存器容量是固定的,当启动的线程数越多,每个线程能分配到的寄存器就越少;如果线程数超过寄存器容量,GPU会把部分数据“溢出”到全局内存,导致性能暴跌。

并行调度

GPU的并行不是“多核心同时跑少量线程”,而是用“数万线程的并发,掩盖内存访问延迟”——依赖Warp调度时分复用

线程的“最小调度单元”——Warp(线约束)

GPU不单独调度“单个线程”,而是以Warp为单位调度———一个Warp包含32个连续的线程(英伟达GPU的固定值,不管架构是开普勒、伏特还是安培)

  • 为什么是 32?因为 GPU 的计算单元(CUDA Core/Tensor Core)是按 32 路 SIMD 设计的 —— 一个 Warp 的 32 个线程会执行 “同一条指令”(比如同时做加法),但操作不同的数据(这就是 “单指令多线程,SIMT”)。
  • 关键现象:如果一个 Warp 中的线程因为 “等待内存访问”(比如等全局内存的数据)而停滞,调度器会立刻切换到另一个 “就绪的 Warp” 继续执行 —— 通过这种 “切换”,让 CUDA Core/Tensor Core 始终有活干,不会因为等待内存而空闲。

Grid → Block → Warp → Thread

当在CUDA中启动一个kernel时,线程的组织是“三层结构”,这对应GPU的调度逻辑

Grid(网格):整个kernel的所有线程 → 由多个Block组成(可跨SM分配)
  ↓
Block(线程块):每个Block包含数百个线程(如256512个)→ 必须分配到同一个SM上(因为Block内的线程要共享共享内存)
  ↓
Warp(线程束):每个Block按32个线程拆分成Warp → 调度器按Warp调度
  ↓
Thread(线程):单个线程 → 执行具体计算

高利用率——时分复用

因为“Warp切换的成本几乎为0”,GPU可以在一个SM上同时管理数百个Warp,通过时分复用让SM的计算单元始终满负荷。

  • 类比理解:就像餐厅的 “服务员(CUDA Core)” 和 “顾客(Warp)”—— 如果一个顾客(Warp)需要等菜(等内存数据),服务员不会闲着,而是去服务另一个顾客(切换 Warp);当第一个顾客的菜好了(内存数据到了),服务员再回来服务他。
  • 核心结论:SM 上的 Warp 数量越多,调度器能切换的 “备选 Warp” 就越多,计算单元的利用率就越高—— 但 Warp 数量受限于 SM 的寄存器和共享内存容量(每个 Warp 需要占用一定的寄存器和共享内存)。

硬件视角看AI Infra优化

AI Infra 优化手段对应的 GPU 硬件特性优化逻辑
模型并行(Model Parallelism)SM 是独立计算单元,全局内存共享将模型层拆分到不同 SM,避免单个 SM 的计算 / 内存瓶颈
算子融合(Operator Fusion)减少全局内存访问(全局内存最慢)将多个算子(如 Conv+BN+ReLU)合并成一个 kernel,避免中间结果写入全局内存
FP8/FP16 量化Tensor Core 支持低精度计算用低精度减少内存带宽占用(FP8 比 FP32 少 75% 带宽),同时适配 Tensor Core 算力
共享内存分块(如 GEMM 分块)共享内存比全局内存快 20-40 倍将大矩阵分成小块,用共享内存缓存,减少全局内存访问次数
线程块大小优化(如选 256)Warp 是 32 线程,SM 资源有限256 是 32 的整数倍(拆成 8 个 Warp),避免 Warp 内有空闲线程;同时匹配 SM 的寄存器 / 共享内存容量