CUDA
这篇文章整理 CUDA 中常见的执行模型、Warp 级原语、性能分析方法以及典型算子优化方向,适合作为后续继续补充实现细节的提纲。
1. CUDA 基础概念
先把几个常见概念区分清楚:
gridblockwarpcontextstream
这些概念分别对应不同层次的执行与调度单位,理解它们是分析 CUDA 程序行为的前提。
2. Warp 级原语与规约
Warp 级操作通常用于减少共享内存访问和同步开销,适合实现高效的 Reduce、Scan 等操作。
2.1 常见接口
1 | T __shfl_sync(unsigned mask, T var, int srcLane, int width = warpSize); |
参数含义:
mask:参与操作的线程掩码,常见写法是0xFFFFFFFFvar:当前线程要交换或参与归约的数据srcLane:从哪个 lane 读取数据delta:相对偏移量laneMask:用于异或交换的掩码width:参与分组的逻辑宽度,默认是一个 warp
2.2 __shfl_sync
从指定线程复制数据到当前线程。
1 | __global__ void kernel() { |
用途:
- 广播某个线程的数据
- warp 内共享中间结果
2.3 __shfl_up_sync
向上取相邻线程的数据,常用于前缀式访问。
1 | __global__ void kernel() { |
2.4 __shfl_down_sync
向下取相邻线程的数据,常用于规约实现。
1 | __global__ void kernel() { |
2.5 __shfl_xor_sync
按照 lane id 的异或结果进行数据交换,常用于 butterfly 风格通信。
1 | __global__ void kernel() { |
2.6 Warp Reduce 示例
1 | __device__ float warpReduceMax(float val) { |
Warp 级规约常见于:
SoftmaxLayerNormRMSNormAttention
3. 性能分析工具
写 CUDA 代码不能只看“能跑”,还需要判断瓶颈类型。
3.1 常见工具
ncu:关注 kernel 级别细节nsys:关注时间线、调用链和整体执行流程
3.2 常见分析维度
compute boundmemory boundbandwidth boundlatency bound
如果一个 kernel 理论计算量不高,但性能仍差,往往说明问题不在算力,而在访存或调度。
4. 访存与共享内存
4.1 Bank Conflict
共享内存访问如果映射到同一个 bank,就会发生 bank conflict,导致访问串行化。
可以重点关注:
- 数据排布方式
- 访问步长
- 是否需要 padding
swizzling机制
4.2 向量化加载
可以使用 float4 等方式进行向量化加载,提高内存吞吐,但要注意:
- 内存对齐
- 数据布局
- 访存是否连续
5. 常见优化手段
5.1 MatMul 优化
典型优化方向:
tiling- 共享内存缓存
ping-pong双缓冲- 减少全局内存重复读取
5.2 循环展开
1 |
循环展开可以减少分支和索引计算开销,但也可能增加寄存器压力,需要结合实际情况评估。
5.3 Kernel 融合与重写
某些基础算子在框架默认实现之外,手写 CUDA kernel 往往有明显收益。
常见例子:
SoftmaxMatMul / GEMMTransposeRMSNormFlashAttention
6. Softmax 作为典型优化案例
Softmax 是 CUDA 优化里非常经典的例子,因为它同时涉及:
- 最大值规约
- 指数计算
- 求和规约
- 数值稳定性
6.1 原始公式
给定输入向量:
$$
\mathbf{z} = [z_1, z_2, …, z_n] \in \mathbb{R}^n
$$
Softmax 定义为:
$$
\text{Softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{n} e^{z_j}}
$$
6.2 数值稳定写法
为了避免指数溢出,通常会先减去最大值:
$$
\text{Softmax}(z_i) = \frac{e^{z_i - \max(\mathbf{z})}}{\sum_{j=1}^{n} e^{z_j - \max(\mathbf{z})}}
$$
6.3 CUDA 实现时的关注点
输入通常可以看成 N x C 的形式,需要考虑:
- 共享内存方案
- 纯 warpReduce 方案
- 共享内存 + warpReduce 混合方案
7. 后续值得继续展开的专题
后续可以继续把这篇文章扩展成下面几个独立章节:
SoftmaxCUDA 实现MatMul / GEMM优化Transpose优化RMSNorm优化FlashAttentionCUDA Graph
8. CUDA Graph
CUDA Graph 适合在重复执行、调用关系稳定的场景下减少 launch 开销。后续可以单独补充:
- 适用场景
- graph capture 流程
- 与 stream 的关系
- 适合哪些推理任务