跳转至

并行体系结构

1. Flynn 分类法

Michael Flynn(1966)根据指令流数据流的并行度将计算机体系结构分为四类:

graph TB
    subgraph "Flynn's Taxonomy"
        direction TB
        A["<b>SISD</b><br/>Single Instruction<br/>Single Data<br/>经典单核 CPU"]
        B["<b>SIMD</b><br/>Single Instruction<br/>Multiple Data<br/>向量处理 / GPU核心"]
        C["<b>MISD</b><br/>Multiple Instruction<br/>Single Data<br/>容错管道(罕见)"]
        D["<b>MIMD</b><br/>Multiple Instruction<br/>Multiple Data<br/>多核 / 分布式"]
    end

    style A fill:#e1f5fe
    style B fill:#e8f5e9
    style C fill:#fff3e0
    style D fill:#f3e5f5
类别 指令流 数据流 代表
SISD 经典单核处理器
SIMD SSE/AVX、NEON、GPU 核心
MISD 航天容错系统(极罕见)
MIMD 多核 CPU、集群、超算

2. SIMD 并行

2.1 向量扩展(CPU SIMD)

同一条指令对多个数据元素同时操作:

扩展 宽度 架构
SSE 128-bit(4×float) x86
AVX2 256-bit(8×float) x86
AVX-512 512-bit(16×float) x86(服务器)
NEON 128-bit ARM
SVE/SVE2 128-2048 bit(可变) ARMv9
RVV 可变(VLEN) RISC-V

加速比上限(忽略标量开销):

\[ S_{\text{SIMD}} = \frac{\text{Vector Width (bits)}}{\text{Element Width (bits)}} \]

例如 AVX-512 处理 32-bit float:\(S = 512 / 32 = 16\times\)

2.2 SIMD 编程模型

  • 编译器自动向量化:编译器检测可向量化的循环
  • Intrinsics:手动调用 SIMD 指令(如 _mm256_add_ps
  • 库抽象:高层库封装(如 Eigen、xsimd)

3. 多核与共享内存

3.1 内存架构

graph TB
    subgraph "UMA (Uniform Memory Access)"
        C1[Core 0] --> BUS1[总线/交叉开关]
        C2[Core 1] --> BUS1
        C3[Core 2] --> BUS1
        BUS1 --> MEM1[共享内存<br/>统一延迟]
    end

    subgraph "NUMA (Non-Uniform Memory Access)"
        C4[Core 0] --> L1[本地内存<br/>快]
        C5[Core 1] --> L1
        C6[Core 2] --> L2[本地内存<br/>快]
        C7[Core 3] --> L2
        L1 <-->|互联<br/>慢| L2
    end
架构 特点 适用规模
UMA 所有核心访存延迟相同 小规模(≤8 核)
NUMA 本地内存快,远端内存慢 多路服务器(数十至数百核)

NUMA 感知编程至关重要——数据应尽量分配在使用它的核心的本地节点上。

3.2 缓存一致性(Cache Coherence)

多核共享内存时,各核心私有 cache 中同一数据可能不一致。

一致性要求

  1. 写传播(Write Propagation):一个核心的写操作最终对所有核心可见
  2. 写串行化(Write Serialization):对同一地址的写操作,所有核心观察到相同顺序

3.3 MESI 协议

最经典的监听协议(Snooping Protocol),每个 cache line 有 4 种状态:

状态 含义
M(Modified) 已修改,仅本 cache 有效,主存过期
E(Exclusive) 未修改,仅本 cache 有效,与主存一致
S(Shared) 未修改,可能多个 cache 持有副本
I(Invalid) 无效,不可使用

状态转换示例

stateDiagram-v2
    [*] --> I
    I --> E: 本地读 (无其他副本)
    I --> S: 本地读 (有其他副本)
    E --> M: 本地写
    S --> M: 本地写 (其他副本→I)
    M --> S: 远端读 (写回主存)
    M --> I: 远端写
    E --> I: 远端写
    S --> I: 远端写
    E --> S: 远端读

MOESI / MESIF 扩展

  • MOESI(AMD):增加 Owned 状态,避免脏数据必须写回主存
  • MESIF(Intel):增加 Forward 状态,指定由谁响应共享请求

3.4 目录协议(Directory Protocol)

监听协议在大规模系统中广播开销大。目录协议使用集中式目录记录每个 cache line 的共享者信息:

  • 适合 NUMA 架构和大规模多核(>16 核)
  • 点对点通信,无需广播
  • 目录条目:状态 + 共享者位向量

3.5 伪共享(False Sharing)

不同核心访问不同变量,但这些变量恰好位于同一 cache line,导致频繁的一致性失效。

\[ \text{性能退化} \propto \text{一致性消息频率} \]

解决方案

  • Cache line 对齐(padding)
  • 每线程独立的数据结构(thread-local)
  • alignas(64) 确保独立变量在不同 cache line

4. GPU 计算模型

4.1 GPU vs CPU 设计哲学

graph LR
    subgraph "CPU: 延迟优化"
        A1[大 Cache] --- A2[复杂控制逻辑]
        A2 --- A3[少量强核心]
        A3 --- A4[乱序执行]
    end

    subgraph "GPU: 吞吐量优化"
        B1[小 Cache] --- B2[简单控制逻辑]
        B2 --- B3[海量弱核心]
        B3 --- B4[线程级并行隐藏延迟]
    end
特性 CPU GPU
核心数 4-128(强核) 数千-数万(CUDA 核心)
控制逻辑 复杂(乱序、分支预测) 简单(顺序执行)
Cache 大(L1+L2+L3 可达 100MB) 小(主要依赖寄存器和共享内存)
内存带宽 ~50-100 GB/s ~1-3 TB/s(HBM)
适合工作负载 串行、分支密集 大规模数据并行

4.2 SIMT(Single Instruction Multiple Thread)

NVIDIA GPU 的执行模型:

  • 线程(Thread):最小执行单元,有独立寄存器和 PC
  • Warp:32 个线程组成一个 warp,锁步执行同一指令
  • 线程块(Block):多个 warp,共享 Shared Memory,在同一 SM 上执行
  • 网格(Grid):多个 Block,跨 SM 分配
Grid
├── Block (0,0)
│   ├── Warp 0: Thread 0-31
│   ├── Warp 1: Thread 32-63
│   └── ...
├── Block (0,1)
│   └── ...
└── ...

4.3 SM(Streaming Multiprocessor)结构

每个 SM 包含:

组件 数量(典型) 功能
CUDA 核心(FP32) 128 浮点/整数运算
Tensor 核心 4 矩阵乘加(AI 加速)
Load/Store 单元 32 访存
SFU(特殊函数) 16 sin, cos, exp 等
Warp 调度器 4 每周期选择就绪 warp 发射
寄存器文件 256 KB 线程私有寄存器
Shared Memory 64-228 KB Block 内线程共享

4.4 分支分化(Warp Divergence)

当 warp 内线程走不同分支路径时:

  • 必须串行执行每条路径(mask 掉不参与的线程)
  • 最差情况:两条路径都执行,吞吐量减半
\[ \text{效率} = \frac{\text{活跃线程数}}{32} \]

优化:减少 warp 内的分支分化,将相同路径的线程分到同一 warp。

4.5 内存层次

内存类型 作用域 延迟 带宽
寄存器 线程私有 1 cycle 最高
Shared Memory Block 内共享 ~5 cycles 很高
L1 Cache SM 级 ~30 cycles
L2 Cache 全局 ~200 cycles 中等
Global Memory (HBM) 全局 ~300-500 cycles ~3 TB/s

关键优化:利用 Shared Memory 作为手动管理的缓存,减少全局内存访问。

5. 互联拓扑

5.1 片上互联

拓扑 结构 适用规模
总线(Bus) 共享介质 ≤4 核
交叉开关(Crossbar) 全连接 ≤16 核(面积 \(O(N^2)\)
环形(Ring) 单/双环 Intel 消费级多核
Mesh 二维网格 众核(Intel Xeon, GPU)

5.2 片间互联

互联 特点 用途
PCIe 通用、中等带宽 CPU-GPU、CPU-SSD
NVLink 超高带宽(900 GB/s) GPU-GPU(NVIDIA)
CXL 缓存一致性扩展 CPU-加速器、内存池化
Infinity Fabric AMD 片间互联 Chiplet 连接
UCIe 开放 Chiplet 互联标准 异构 Chiplet

6. 并行编程模型

模型 抽象级别 适用硬件
Pthreads / std::thread 低级线程 多核 CPU
OpenMP 编译指导(#pragma 多核 CPU
CUDA / HIP GPU 并行编程 NVIDIA / AMD GPU
SYCL / oneAPI 异构并行(跨设备) CPU + GPU + FPGA
MPI 消息传递(分布式内存) 集群、超算

7. 性能指标与分析

7.1 加速比与效率

\[ S(p) = \frac{T(1)}{T(p)}, \quad E(p) = \frac{S(p)}{p} \]
  • 理想线性加速比\(S(p) = p\)\(E(p) = 1\)
  • 实际受限于:串行部分(Amdahl)、通信开销、负载不均衡

7.2 Roofline 模型

衡量程序受计算还是带宽限制:

\[ \text{Performance} = \min(\text{Peak FLOPS}, \text{Bandwidth} \times \text{Operational Intensity}) \]

其中操作强度 \(\text{OI} = \text{FLOPs} / \text{Bytes transferred}\)

  • \(\text{OI} < \text{Ridge Point}\)带宽受限(memory-bound)
  • \(\text{OI} > \text{Ridge Point}\)计算受限(compute-bound)

优化策略

  • Memory-bound:提升数据复用、预取、压缩、使用更高带宽内存
  • Compute-bound:利用 SIMD、Tensor 核心、算法优化减少运算量

8. 异构计算与领域专用架构

8.1 异构 SoC

现代 SoC 集成多种计算单元:

单元 擅长任务
CPU 大核 串行、控制密集
CPU 小核 低功耗后台任务
GPU 图形、大规模数据并行
NPU/TPU 神经网络推理
DSP 信号处理
ISP 图像处理

8.2 领域专用加速器

加速器 应用 关键特点
Google TPU 机器学习 脉动阵列、BF16/INT8
NVIDIA Tensor Core 矩阵乘加 FP16/BF16/INT8/FP8
Apple Neural Engine 端侧 AI 推理 高能效
FPGA 可重构计算 灵活但开发难度高

导航


评论 #