【CUDA5】为什么“少做几次”有时候比“算得更快”更重要?
Kernel 一段让 GPU 执行的程序x x 1 x x * 2 x torch.relu(x)如果你用python的角度来看只有三行但是 GPU 可能把它执行成多个 Kernel。CPU ↓ Launch Kernel #1 ↓ GPU: x x 1Kernel 1 │ VRAM ──→ x1 ──→ VRAM │ ↓ Kernel 2 │ VRAM ──→ x×2 ──→ VRAM │ ↓ Kernel 3 │ VRAM ──→ ReLU ──→ VRAM每个步骤可能都需要启动一个GPU Kernel这三行代码对应三个Kernel如果有1000000个元素不断访问GPU,数据被反复从 Global Memory 读出来又写回去事实上可以将想做的一次性完成这样只需要一次主要的读取和一次主要的写回这就是Kernel FusionGlobal Memory ↓ Kernel │ ├── 1 ├── ×2 └── ReLU ↓ Global Memory第一Kernel Launch它将原来多个launch融合第二Global Memory Traffic,它将读写一次性全部完成Memory-bound ↓ 减少 Memory Traffic ↓ Kernel Fusion ↓ 性能提升所以当看到一个GPU程序很慢不要第一反应就说GPU算力不够而是先① Kernel 太多 ↓ ② Kernel Launch overhead ↓ ③ Global Memory 访问太多 ↓ ④ Memory access 是否 coalesced ↓ ⑤ 有没有数据复用 ↓ ⑥ 能不能 Fusion ↓ ⑦ 是 Memory-bound 还是 Compute-bound ↓ ⑧ GPU utilization 怎么样