第16章 §01 · SIMD 与 GPU 编程总览 · 讲解稿¶
章节定位: Ch16 §00 总览 → §01 硬件基础 承接: Ch13 计算机架构 + Ch17 AI 推理 (前置依赖) 篇幅: ~5500 字 / 阅读 14 分钟 / 讲解 28 分钟
一 · 一句话总览¶
SIMD/GPU = 硬件加速的"屠龙刀"。理解 CPU SIMD (AVX/NEON) + GPU (CUDA/Triton) 是性能工程师的"分水岭"。
二 · 心智模型¶
把计算想象成工人搬砖: - CPU 单线程: 1 个工人搬 1 块砖 → 慢但灵活 - CPU SIMD: 1 个工人同时搬 4 块砖 (AVX-256) → 快 4 倍 - GPU 1000 线程: 1000 个工人同时搬砖 → 快 1000 倍 (但要能并行) - TPU 矩阵单元: 1 个超大工人一次搬 128×128 砖 → 块大但密集
核心: 数据并行 = 性能。
三 · 章节主线 (5 段)¶
第 1 段 · SIMD 基础 (8 分钟)¶
3.1.1 什么是 SIMD¶
SIMD = Single Instruction Multiple Data, 单指令多数据: - 1 个指令操作多个数据 (4 / 8 / 16 / 32 个同时) - 寄存器宽度: 128 (SSE) → 256 (AVX) → 512 (AVX-512) - 1 个 AVX-512 寄存器 = 16 个 FP32
3.1.2 主流 SIMD 指令集¶
| 指令集 | 厂商 | 宽度 | 状态 |
|---|---|---|---|
| SSE / SSE2/3/4 | Intel/AMD | 128-bit | 旧 |
| AVX / AVX2 | Intel/AMD | 256-bit | 主流 |
| AVX-512 | Intel | 512-bit | 服务器 |
| NEON | ARM | 128-bit | 移动 |
| SVE / SVE2 | ARM | 128-2048 | 服务器 |
| RISC-V V | 开源 | 可变 | 新兴 |
3.1.3 SIMD 编程模型¶
// 标量
for (int i = 0; i < n; i++) {
c[i] = a[i] + b[i];
}
// SIMD (intrinsics)
__m256 va = _mm256_load_ps(a);
__m256 vb = _mm256_load_ps(b);
__m256 vc = _mm256_add_ps(va, vb);
_mm256_store_ps(c, vc);
第 2 段 · GPU 架构 (10 分钟)¶
3.2.1 CPU vs GPU¶
| 指标 | CPU | GPU |
|---|---|---|
| 核心数 | 4-64 | 1000-10000 |
| 频率 | 3-5 GHz | 1-2 GHz |
| 缓存 | MB | KB |
| 适用 | 顺序 / 串行 | 数据并行 |
| 能耗 | 中 | 高 |
| 内存 | DDR | HBM (大) |
3.2.2 NVIDIA GPU 架构¶
SM (Streaming Multiprocessor) = GPU 的核心: - 1 SM = 64-128 CUDA 核心 - Ampere (A100): 108 SM × 64 core = 6912 cores - Hopper (H100): 132 SM × 128 core = 16896 cores - 每个 SM 有共享内存 + Tensor Core
3.2.3 Memory Hierarchy¶
Register (per thread) ~ns ~32 KB/SM
Shared Memory (per block) ~10 ns ~100 KB/SM
L1 Cache (per SM) ~20 ns ~128 KB/SM
L2 Cache (per GPU) ~100 ns ~50 MB
HBM (global) ~500 ns 40-80 GB (A100/H100)
Host Memory (DMA) ~μs TB
3.2.4 CUDA 编程模型¶
__global__ void vector_add(float *a, float *b, float *c, int n) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < n) c[idx] = a[idx] + b[idx];
}
int main() {
int n = 1024 * 1024;
int threads = 256;
int blocks = (n + threads - 1) / threads;
vector_add<<<blocks, threads>>>(a, b, c, n);
cudaDeviceSynchronize();
}
第 3 段 · 高级 GPU 优化 (12 分钟)¶
3.3.1 Memory Coalescing¶
核心: 连续线程访问连续内存 → 1 次 transaction。
3.3.2 Shared Memory Bank Conflict¶
Shared memory 分 32 bank: - 同 bank 不同地址 → conflict (串行) - 不同 bank → 并行
__shared__ float sm[32][32];
// 访问 sm[tid][0] for tid in 0..31 → 全 bank 0 → 31 个 conflict
// 解决: sm[tid][tid] (对角)
3.3.3 Occupancy¶
Occupancy = 活跃 warp 数 / 最大 warp 数:
- 受 register / shared mem 限制
- 一般 50%+ 即可
- 工具: nvcc --ptxas-options=-v
3.3.4 Tensor Core¶
矩阵乘加速器:
- A100: TF32 156 TFLOPS, FP16 312 TFLOPS
- H100: FP8 3.3 PFLOPS, FP16 1.9 PFLOPS
- 调用: mma.sync.aligned.m16n8k16.row.col.f32.tf32.tf32.f32
第 4 段 · Triton 入门 (10 分钟)¶
3.4.1 Triton 是什么¶
Triton = Pythonic GPU 编程语言 (OpenAI 2021): - 比 CUDA 简单 (Python 风格) - 自动优化 (memory coalescing / 共享内存) - 编译为 PTX (NVIDIA GPU)
3.4.2 Triton 编程示例¶
import triton
import triton.language as tl
@triton.jit
def add_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK: tl.constexpr):
pid = tl.program_id(0)
offset = pid * BLOCK + tl.arange(0, BLOCK)
mask = offset < n
x = tl.load(x_ptr + offset, mask=mask)
y = tl.load(y_ptr + offset, mask=mask)
tl.store(out_ptr + offset, x + y, mask=mask)
def add(x, y):
out = torch.empty_like(x)
n = x.numel()
BLOCK = 1024
grid = (triton.cdiv(n, BLOCK),)
add_kernel[grid](x, y, out, n, BLOCK=BLOCK)
return out
3.4.3 Triton vs CUDA¶
| 维度 | Triton | CUDA |
|---|---|---|
| 易用性 | ✅ Python | ❌ C++ |
| 性能 | 80-95% SOTA | 100% SOTA |
| 控制粒度 | 中 | 极细 |
| 适用 | 算子实现 / Kernel 优化 | 极致优化 |
第 5 段 · 实战案例 (8 分钟)¶
3.5.1 案例 1: 矩阵乘 SIMD¶
// AVX-512 8x8 矩阵乘
void matmul_avx512(const float *A, const float *B, float *C, int M, int N, int K) {
for (int i = 0; i < M; i += 8) {
for (int j = 0; j < N; j += 16) {
__m512 c[8] = {_mm512_setzero_ps(), ...};
for (int k = 0; k < K; k++) {
__m512 b = _mm512_loadu_ps(&B[k * N + j]);
for (int ii = 0; ii < 8; ii++) {
__m512 a = _mm512_set1_ps(A[i * K + ii * K + k]);
c[ii] = _mm512_fmadd_ps(a, b, c[ii]);
}
}
for (int ii = 0; ii < 8; ii++) _mm512_storeu_ps(&C[(i+ii)*N + j], c[ii]);
}
}
}
3.5.2 案例 2: Softmax CUDA Kernel¶
__global__ void softmax_kernel(const float *in, float *out, int n) {
extern __shared__ float smem[];
int tid = threadIdx.x;
int gid = blockIdx.x * blockDim.x + tid;
// 1. 找 max
float max_val = -INFINITY;
if (gid < n) max_val = in[gid];
smem[tid] = max_val;
__syncthreads();
for (int s = blockDim.x / 2; s > 0; s >>= 1) {
if (tid < s) smem[tid] = max(smem[tid], smem[tid + s]);
__syncthreads();
}
float block_max = smem[0];
// 2. exp & sum
float exp_val = (gid < n) ? expf(in[gid] - block_max) : 0;
smem[tid] = exp_val;
__syncthreads();
for (int s = blockDim.x / 2; s > 0; s >>= 1) {
if (tid < s) smem[tid] += smem[tid + s];
__syncthreads();
}
float sum = smem[0];
// 3. divide
if (gid < n) out[gid] = exp_val / sum;
}
四 · 关键论文 / 工具¶
| 工具 | 出品 | 用途 |
|---|---|---|
| CUDA Toolkit | NVIDIA | GPU 编程 |
| Triton | OpenAI | Pythonic GPU |
| rocPRIM / HIP | AMD | AMD GPU |
| oneAPI / SYCL | Intel | 跨厂商 |
| Numba | Continuum | Python JIT |
五 · 跨章连接¶
| 章节 | 关联 |
|---|---|
| Ch13 §02 | CPU 架构 |
| Ch17 §01 | 量化 |
| Ch17 §02 | 高效架构 (Flash Attention) |
| Ch18 §03 | 分布式 GPU |
六 · 自测 5 题¶
- SIMD 与 SIMT 区别?
- 什么是 Memory Coalescing?
- Tensor Core 主要用于?
- Triton 相对 CUDA 的优势?
- SM 与 CUDA Core 关系?
七 · 一句话总结¶
SIMD/GPU = 数据并行的硬件加速。AVX-512 加速 CPU 4-16 倍, GPU 加速 100-1000 倍, Triton 让 GPU 编程平民化。理解 memory hierarchy + coalescing + occupancy = 性能优化基础。