0%

CUDA 编程模型基础

CUDA 编程模型基础

一句话定位:理解 GPU 的两件事——线程怎么被组织和调度数据放在哪一层存储。用大数据的调度与分层存储直觉去套,学习成本最低。

1. 线程层次:Grid → Block → Thread

  • Grid:一次 Kernel 启动的全部线程,由多个 Block 组成。
  • Block:线程块,块内线程可通过共享内存通信与 __syncthreads() 同步;一个 Block 必须整体调度到同一个 SM 上。
  • Thread:最小编程单位,通过 blockIdx * blockDim + threadIdx 计算全局索引。

关键区分(面试易错点):

  • Warp(32 线程)是真实的调度单位。硬件以 warp 为粒度取指与执行(SIMT),warp 内 32 线程执行同一条指令。因此若 warp 内线程走了不同分支,会产生warp divergence(分支被串行执行),性能下降。Block 大小通常取 32 的倍数就是这个原因。
  • SM(Streaming Multiprocessor)是执行硬件:包含 CUDA Core、寄存器文件、共享内存、warp 调度器。多个 Block 可并发驻留同一 SM(占用率 occupancy 由寄存器/共享内存用量决定)。

2. 显存层次(速度差数量级)

从快到慢:

层级 作用域 相对速度
寄存器 (Register) 单线程私有 最快(~1 周期)
共享内存 (Shared Memory) Block 内共享,片上 SRAM 很快(~几十周期)
L2 Cache 全 GPU 共享 中等
全局内存 (Global / HBM) 全 GPU + Host 可见 最慢(数百周期)

核心结论:优化 GPU 程序的主线是”把数据尽量留在高层级”——用共享内存复用数据、保证全局内存合并访问(coalesced),减少对 HBM 的读写次数。这正是 FlashAttention(3.7)的核心思想。

3. 可迁移类比(我的表达桥梁)

  • Warp 调度 ≈ Spark Task 调度:都是把大任务切成固定粒度的执行单元批量调度;warp divergence ≈ Task 内分支导致的负载不均。
  • 显存层次 ≈ 内存/磁盘分层存储:寄存器/共享内存 ≈ 内存缓存,全局内存(HBM) ≈ 磁盘/远端存储;”减少 HBM 读写” ≈ “减少 Shuffle 落盘与网络传输”,都是把 IO 成本而非算力当作首要瓶颈。

参考:《CUDA C++ Programming Guide》