lowpower_ai

第9章:数字存内计算架构

本章深入探讨数字存内计算(Processing-In-Memory, PIM)架构,这是突破冯诺依曼瓶颈、大幅降低数据搬移功耗的关键技术。我们将从存储墙问题出发,系统分析SRAM和DRAM两种主流数字PIM实现方案,探讨算子映射策略,并通过Samsung HBM-PIM等工业案例理解实际设计权衡。本章还将深入讨论近数据计算中的缓存一致性挑战,为设计高效能数字PIM系统提供理论和实践指导。

9.1 冯诺依曼瓶颈与存储墙

9.1.1 冯诺依曼架构的根本限制

冯诺依曼架构自1945年提出以来,一直是现代计算机系统的基础。其核心特征是计算单元与存储单元的物理分离,通过总线进行数据交换。这种架构在传统计算中运行良好,但在数据密集型的AI推理任务中暴露出严重的效率问题。

从信息理论角度看,冯诺依曼架构的根本问题在于信息的时空局部性失配。AI推理中的张量运算具有高度的数据并行性,理想情况下应该在数据存储位置就地计算。然而,传统架构强制要求数据必须经过以下路径:

存储器 → 缓存层次 → 寄存器 → ALU → 寄存器 → 缓存层次 → 存储器

这种往返搬移不仅增加延迟,更关键的是消耗大量能量。根据45nm工艺节点的测量数据:

可见,数据搬移的能耗比实际计算高出2-3个数量级。对于具有百亿参数的大模型,仅权重读取就需要数十焦耳的能量,这在边缘设备上是不可接受的。

9.1.2 存储墙的量化分析

存储墙(Memory Wall)问题可以从带宽和功耗两个维度量化分析。我们定义计算强度(Computational Intensity)为:

\[CI = \frac{\text{Operations}}{\text{Memory Access}} \quad [\text{OPs/Byte}]\]

对于典型的矩阵乘法 $\mathbf{C} = \mathbf{A} \times \mathbf{B}$,其中 $\mathbf{A} \in \mathbb{R}^{M \times K}$,$\mathbf{B} \in \mathbb{R}^{K \times N}$:

当无法充分重用数据时,$CI$ 值很低。以 GEMM 为例,假设 $M=N=K=1024$,使用FP16: \(CI = \frac{2 \times 1024^3}{3 \times 1024^2 \times 2} \approx 341 \text{ OPs/Byte}\)

而现代GPU的计算吞吐量与内存带宽之比(机器平衡点)为: \(\text{Machine Balance} = \frac{\text{Peak FLOPS}}{\text{Memory Bandwidth}}\)

以NVIDIA A100为例:

当 $CI < \text{Machine Balance}$ 时,系统受内存带宽限制。这解释了为什么许多AI工作负载无法充分利用计算资源。

9.1.3 数据搬移的能耗分解

数据搬移能耗可以分解为多个层次,每个层次的访问能耗呈指数级增长:

寄存器文件 (RF):  0.1-0.5 pJ/access
L1 Cache:        1-5 pJ/access  
L2 Cache:        5-20 pJ/access
L3 Cache:        20-50 pJ/access
DRAM:            200-640 pJ/access
Off-chip I/O:    1000-2500 pJ/access

考虑一个简单的向量加法 $\mathbf{c} = \mathbf{a} + \mathbf{b}$,其中向量长度为 $n$:

这个巨大的差异促使我们重新思考计算架构。数据搬移的能耗还可以用RC模型建模:

\[E_{wire} = \alpha \cdot C_{wire} \cdot V_{dd}^2 \cdot L\]

其中 $C_{wire}$ 是单位长度电容,$L$ 是互连长度,$\alpha$ 是活动因子。随着芯片面积增大,长距离互连的能耗问题愈发严重。

9.1.4 存内计算的基本原理

存内计算(Processing-In-Memory, PIM)通过将计算单元集成到存储阵列中,从根本上消除了数据搬移开销。其核心思想是利用存储阵列的内在并行性执行计算。

数字PIM的基本操作模式包括:

  1. 行并行计算:同时激活多行,在位线上执行逻辑运算
  2. 列并行计算:对整行数据并行处理
  3. 阵列级计算:利用存储阵列作为查找表或计算矩阵

以SRAM为例,传统读操作只激活一行,而PIM模式可以:

传统模式:激活Row[i] → 读取Data[i] → 送至ALU
PIM模式:激活Row[i]和Row[j] → 位线上直接计算AND/OR → 写回Row[k]

这种计算方式的能效优势来自:

存内计算的理论能效极限可以用Landauer原理估算: \(E_{min} = k_B T \ln(2) \approx 2.87 \times 10^{-21} \text{ J/bit} \quad (@300K)\)

虽然实际电路远未达到这个极限,但相比传统架构已有数量级的改进空间。

9.2 SRAM数字存内计算

9.2.1 SRAM-PIM基本架构

SRAM作为片上存储的主力,具有高速、低延迟的特点,是实现数字PIM的理想载体。标准6T SRAM单元由两个交叉耦合的反相器和两个访问晶体管组成:

     VDD                VDD
      |                  |
    ┌─┴─┐              ┌─┴─┐
    │MP1│              │MP2│
    └─┬─┘              └─┬─┘
      ├────────┬────────┤
      │        │        │
    ┌─┴─┐    ┌─┴─┐    ┌─┴─┐
WL──┤MN3├────┤   ├────┤MN4├──WL
    └───┘    │ Q │    └───┘
             └───┘
      │                  │
    ┌─┴─┐              ┌─┴─┐
    │MN1│              │MN2│
    └───┘              └───┘
      │                  │
     GND                GND
      │                  │
     BL                 BLB

在PIM模式下,SRAM阵列不仅存储数据,还执行计算。关键创新在于利用位线(BL)的电荷共享机制实现逻辑运算。基本的SRAM-PIM架构包括:

  1. 计算使能逻辑:控制多行同时激活
  2. 感知放大器增强:支持多值检测
  3. 局部ALU:每列或每几列配置简单运算单元
  4. 结果缓冲器:暂存中间计算结果

典型的SRAM-PIM操作序列:

1. 预充电位线至VDD/2
2. 同时激活多个字线(WL)
3. 位线电压根据存储值发生变化
4. 感知放大器检测并放大信号
5. 结果写回指定行或输出

这种架构的关键优势是复用现有SRAM结构,仅需少量额外逻辑即可实现PIM功能。

9.2.2 位线计算技术

位线计算是SRAM-PIM的核心技术,通过控制多行激活实现不同的逻辑功能。当两行同时激活时,位线电压由两个单元的存储值共同决定:

对于AND操作:

位线电压可以建模为: \(V_{BL} = V_{pre} + \frac{\Delta Q}{C_{BL}}\)

其中 $V_{pre}$ 是预充电压,$\Delta Q$ 是电荷变化量,$C_{BL}$ 是位线电容。

更复杂的运算通过级联基本操作实现。例如,全加器可以分解为:

Sum = A ⊕ B ⊕ Cin
Cout = AB + BCin + ACin

每个基本操作映射到一次或多次位线计算。通过精心设计激活序列,可以实现:

位线计算的能效优势来自: \(E_{BL-compute} = C_{BL} \cdot V_{DD} \cdot \Delta V \approx 0.5-2 \text{ pJ/op}\)

相比传统ALU(~10-50 pJ/op),能效提升5-10倍。

9.2.3 多行激活与并行计算

传统SRAM设计中,多行激活会导致位线冲突和数据破坏。PIM设计通过以下技术实现安全的多行激活:

  1. 弱激活技术:降低字线电压,限制单元驱动能力 \(V_{WL} = V_{DD} - \Delta V_{margin}\)

  2. 时序控制:精确控制激活时间窗口 \(t_{active} < \frac{C_{BL} \cdot \Delta V_{sense}}{I_{cell}}\)

  3. 隔离晶体管:在关键路径插入隔离开关

并行度分析:假设SRAM阵列有 $m$ 行 $n$ 列,每次激活 $k$ 行:

实际设计中,$k$ 的选择需要平衡:

典型设计选择 $k=2-8$,对应不同的计算模式:

k=2: 基本逻辑运算(AND/OR)
k=3: 三输入函数(全加器)
k=4-8: 复杂函数或查找表

9.2.4 SRAM-PIM的功耗优势

SRAM-PIM的功耗优势可以从多个层面分析:

1. 数据搬移消除 传统路径:SRAM → L1 → ALU → L1 → SRAM PIM路径:SRAM内部完成

能耗节省: \(\Delta E = n \times (E_{L1-read} + E_{L1-write} + E_{interconnect}) \approx 10-20 \text{ pJ/op}\)

2. 电压摆幅降低

功耗降低比例: \(\frac{P_{PIM}}{P_{traditional}} = \left(\frac{\Delta V_{small}}{V_{DD}}\right)^2 \approx 0.01-0.04\)

3. 并行计算摊销 固定开销(如译码、时钟)被大量并行操作摊销: \(E_{per-op} = \frac{E_{fixed} + n \times E_{variable}}{n}\)

当 $n$ 足够大时,$E_{per-op} \to E_{variable}$,接近理论下限。

4. 实测功耗对比 以1MB SRAM阵列执行矩阵乘法为例(28nm工艺):

指标 传统架构 SRAM-PIM 改进比
动态功耗 125 mW 18 mW 6.9×
静态功耗 15 mW 16 mW 0.94×
能效 0.8 TOPS/W 5.5 TOPS/W 6.9×
面积开销 基准 +8% -

SRAM-PIM特别适合以下场景:

设计优化建议:

  1. 采用分层位线减少电容
  2. 使用本地感知放大器降低延迟
  3. 实现可配置并行度适应不同工作负载
  4. 集成压缩解码器直接处理压缩数据

9.3 DRAM-PIM架构(HBM-PIM)

9.3.1 DRAM存储层次与带宽限制

DRAM作为主存储器,容量大但访问延迟高,是系统性能的主要瓶颈。现代DRAM的层次结构为:

Channel → Rank → Chip → Bank → Subarray → Mat → Cell

每一层都引入了带宽限制:

带宽利用率可以建模为: \(BW_{eff} = BW_{peak} \times \eta_{bus} \times \eta_{bank} \times \eta_{row}\)

其中:

实际有效带宽仅为峰值的25-45%。AI工作负载的随机访问模式使情况更糟:

以Transformer的注意力计算为例,访问模式近似随机: \(P(row\_miss) = 1 - \frac{1}{n_{rows}} \approx 1 \quad (n_{rows} >> 1)\)

每次行未命中的开销: \(t_{penalty} = t_{PRE} + t_{ACT} + t_{CAS} \approx 50-60 \text{ ns}\)

这相当于损失200-240个时钟周期的计算机会。

9.3.2 HBM架构与PIM集成

高带宽内存(HBM)通过3D堆叠和硅通孔(TSV)技术大幅提升带宽:

     ┌─────────────────┐
     │   Logic Die     │  ← PIM计算单元
     ├─────────────────┤
     │   DRAM Die 8    │  ← 16个Bank
     ├─────────────────┤     
     │   DRAM Die 7    │     每个Bank: 
     ├─────────────────┤     - 16-32MB容量
     │      ...        │     - 独立控制
     ├─────────────────┤     - 局部计算单元
     │   DRAM Die 1    │
     └─────────────────┘
            ││││
            ││││  ← TSV (每个~10-20 μm)
            ││││
     ┌─────────────────┐
     │  Silicon Inter- │
     │     poser       │
     └─────────────────┘

HBM-PIM的关键创新:

  1. Bank级PIM单元:每个Bank配置专用计算逻辑
  2. TSV互连:提供~1TB/s的内部带宽
  3. 近数据处理:计算单元距离存储阵列<1mm

HBM2E规格(8-Hi堆叠):

PIM集成后的改进: \(Speedup = \frac{BW_{internal}}{BW_{external}} = \frac{1024 \text{ GB/s}}{460 \text{ GB/s}} \approx 2.2×\)

但更重要的是消除了片外数据传输: \(E_{saved} = n_{ops} \times (E_{HBM-controller} + E_{PHY} + E_{PCB}) \approx 15-20 \text{ pJ/bit}\)

9.3.3 Bank级并行计算

Bank级并行是HBM-PIM的核心优势。每个Bank可以独立执行计算,实现大规模并行:

并行度分析:

Bank内计算架构:

Row Buffer (8KB)
    ↓
┌─────────────────────────┐
│  16×16-bit MAC Array    │ ← 可编程计算单元
├─────────────────────────┤
│  Local Register File    │ ← 256B局部存储
├─────────────────────────┤
│  Control Logic          │ ← 指令译码
└─────────────────────────┘
    ↓
Global I/O

计算模式:

  1. SIMD模式:所有Bank执行相同操作
    • 适合:矩阵乘法、卷积
    • 吞吐量:2048 × 16-bit MAC × 1.2GHz = 4.9 TOPS
  2. MIMD模式:各Bank独立操作
    • 适合:稀疏运算、不规则访问
    • 灵活性高但编程复杂
  3. Pipeline模式:Bank间流水线
    • 适合:深度网络推理
    • 降低中间结果传输

功耗效率分析: \(\eta_{energy} = \frac{E_{compute}}{E_{compute} + E_{access}} = \frac{0.5}{0.5 + 20} \approx 2.4\%\)

PIM后: \(\eta_{energy}^{PIM} = \frac{E_{compute}}{E_{compute} + E_{local}} = \frac{0.5}{0.5 + 2} = 20\%\)

能效提升约8倍。

9.3.4 DRAM刷新与PIM操作协调

DRAM需要定期刷新以保持数据,这与PIM操作产生冲突。标准DRAM刷新要求:

PIM操作期间的刷新策略:

1. 刷新感知调度 将PIM操作划分为可中断的子任务: \(T_{task} < T_{refresh\_interval} - T_{refresh\_time}\)

典型值:$T_{task} < 7.8\mu s - 350ns \approx 7.45\mu s$

2. 选择性刷新 只刷新包含有效数据的行:

if (row.valid && row.age > threshold):
    refresh(row)
else:
    skip(row)

可减少30-50%的刷新开销。

3. PIM操作作为隐式刷新 某些PIM操作(如行复制)可以起到刷新作用: \(Refresh_{implicit} = Read_{row} + Write_{row}\)

4. 刷新并行化 利用Bank级并行,交错执行刷新和PIM:

Bank0: PIM操作
Bank1: 刷新
Bank2: PIM操作
Bank3: 刷新
...

刷新对PIM性能的影响建模: \(Performance_{degradation} = \frac{T_{refresh}}{T_{window}} \times P_{conflict}\)

其中 $P_{conflict}$ 是刷新与PIM操作冲突的概率。

优化后的协调机制可将性能损失控制在5%以内,关键技术包括:

9.4 数字PIM的算子映射

将神经网络算子高效映射到PIM硬件是实现性能和能效优势的关键。不同于传统处理器的串行执行模型,PIM需要充分利用存储阵列的内在并行性,同时考虑数据布局、访问模式和硬件约束。本节详细分析主要算子的映射策略,为PIM编译器设计提供理论基础。

9.4.1 矩阵乘法映射策略

矩阵乘法是深度学习的核心算子,占据了推理计算的70-90%。对于矩阵乘法 $\mathbf{C} = \mathbf{A} \times \mathbf{B}$,其中 $\mathbf{A} \in \mathbb{R}^{M \times K}$,$\mathbf{B} \in \mathbb{R}^{K \times N}$,PIM映射需要考虑三个维度的并行化。

1. 输出静态映射(Output Stationary)

每个PIM单元负责计算输出矩阵的一个或多个元素: \(C_{ij} = \sum_{k=1}^{K} A_{ik} \times B_{kj}\)

映射策略:

Bank[i]负责计算C[i, :]
for k in range(K):
    broadcast A[i, k] to all MACs in Bank[i]
    load B[k, :] to MAC array
    MAC_array += A[i, k] * B[k, :]

优势:输出无需移动,减少写回开销 劣势:输入数据需要广播,增加互连压力

2. 权重静态映射(Weight Stationary)

将权重矩阵 $\mathbf{B}$ 预先加载到PIM单元:

每个Bank存储B的若干列
for batch in input_batches:
    for i in range(M):
        broadcast A[i, :] to all Banks
        Bank[j] computes C[i, j] = A[i, :] · B[:, j]

这种映射特别适合推理场景,因为权重是静态的:

能耗分析: \(E_{WS} = M \times (E_{broadcast} + N \times E_{MAC} + N \times E_{accumulate})\)

3. 行并行分块策略

对于大矩阵,采用分块策略以适应有限的存储容量:

\[\mathbf{C} = \begin{bmatrix} \mathbf{A}_1 \\ \mathbf{A}_2 \\ \vdots \end{bmatrix} \times [\mathbf{B}_1, \mathbf{B}_2, \cdots] = \begin{bmatrix} \mathbf{A}_1\mathbf{B}_1 & \mathbf{A}_1\mathbf{B}_2 & \cdots \\ \mathbf{A}_2\mathbf{B}_1 & \mathbf{A}_2\mathbf{B}_2 & \cdots \\ \vdots & \vdots & \ddots \end{bmatrix}\]

块大小选择需要平衡:

4. 稀疏感知映射

对于稀疏矩阵(如剪枝后的权重),采用压缩存储格式:

CSR格式映射:

values[]:  非零元素值
col_idx[]: 列索引
row_ptr[]: 行指针

PIM执行稀疏矩阵乘法:

for i in range(M):
    start = row_ptr[i]
    end = row_ptr[i+1]
    for j in range(start, end):
        col = col_idx[j]
        val = values[j]
        C[i, :] += val * B[col, :]  # 只计算非零元素

稀疏度 $s$ 时的加速比: \(Speedup = \frac{1}{1-s} \times \eta_{overhead}\)

其中 $\eta_{overhead}$ 考虑索引开销,典型值0.7-0.9。

9.4.2 卷积操作的PIM实现

卷积运算可以转换为矩阵乘法(im2col),但这会引入大量数据复制。PIM允许直接在存储器中执行卷积,避免数据重排。

1. 直接卷积映射

对于卷积 $Y = X * W$,其中:

PIM映射策略:

将输入特征图X分布存储在多个Bank
每个Bank负责输出特征图的一个区域
for oc in range(C_out):
    for ic in range(C_in):
        for kh in range(K_h):
            for kw in range(K_w):
                weight = W[oc, ic, kh, kw]
                # 并行计算所有输出位置
                Y[oc, :, :] += weight * X[ic, shifted(kh, kw)]

2. 滑窗缓冲优化

利用卷积的滑窗特性,实现数据重用:

     Input Feature Map
    ┌─────────────────┐
    │ █ █ █ ░ ░ ░ ░ ░ │ ← 窗口1
    │ █ █ █ ░ ░ ░ ░ ░ │
    │ █ █ █ ░ ░ ░ ░ ░ │
    │ ░ █ █ █ ░ ░ ░ ░ │ ← 窗口2(重用2列)
    │ ░ █ █ █ ░ ░ ░ ░ │
    │ ░ █ █ █ ░ ░ ░ ░ │
    └─────────────────┘

重用率计算: \(Reuse = \frac{K_h \times K_w - 1}{K_h \times K_w} \times 100\%\)

对于3×3卷积,重用率达88.9%。

3. 深度可分离卷积的PIM优化

深度可分离卷积分为深度卷积和逐点卷积两步:

深度卷积(Depthwise):

Bank[c]存储Channel[c]的数据
Bank[c]执行: Y_dw[c] = X[c] * W_dw[c]

逐点卷积(Pointwise):

总计算量降低比: \(\frac{Compute_{DSC}}{Compute_{Conv}} = \frac{1}{C_{out}} + \frac{1}{K^2}\)

对于 $K=3, C_{out}=256$,计算量降至原来的11.5%。

4. Winograd卷积的PIM实现

Winograd算法通过预处理减少乘法次数。对于F(2,3)(2×2输出,3×3卷积核):

变换矩阵: \(B_T = \begin{bmatrix} 1 & 0 & -1 & 0 \\ 0 & 1 & 1 & 0 \\ 0 & -1 & 1 & 0 \\ 0 & 1 & 0 & -1 \end{bmatrix}\)

PIM实现步骤:

  1. 输入变换:$\tilde{X} = B_T X B$(使用PIM的矩阵运算)
  2. 权重变换:$\tilde{W} = G W G_T$(离线预计算)
  3. 逐元素乘法:$\tilde{Y} = \tilde{X} \odot \tilde{W}$(高度并行)
  4. 输出变换:$Y = A_T \tilde{Y} A$

乘法减少率: \(\frac{Mult_{Winograd}}{Mult_{Direct}} = \frac{(m+r-1)^2}{m^2 r^2}\)

对于F(2,3):$\frac{16}{36} = 44.4\%$

9.4.3 激活函数与非线性操作

非线性激活函数是神经网络的关键组件,但在PIM中实现较为困难。主要策略包括查找表(LUT)、分段线性近似和专用硬件。

1. 查找表实现

将激活函数预计算并存储在SRAM中:

ReLU:    LUT[x] = max(0, x)
Sigmoid: LUT[x] = 1/(1+exp(-x))
Tanh:    LUT[x] = tanh(x)

地址映射(8-bit量化): \(addr = \lfloor \frac{x - x_{min}}{x_{max} - x_{min}} \times 255 \rfloor\)

存储开销:

2. 分段线性近似

将非线性函数分段线性化:

\[f(x) \approx \begin{cases} a_0x + b_0, & x \in [x_0, x_1) \\ a_1x + b_1, & x \in [x_1, x_2) \\ \vdots \\ a_nx + b_n, & x \in [x_n, x_{n+1}) \end{cases}\]

PIM实现:

segment = binary_search(x, breakpoints[])
result = slopes[segment] * x + intercepts[segment]

误差控制: \(\epsilon_{max} = \max_{x \in [x_i, x_{i+1}]} |f(x) - (a_ix + b_i)|\)

对于ReLU6,只需2段;对于Sigmoid,通常需要4-8段以达到1%精度。

3. GELU的高效近似

GELU激活函数:$GELU(x) = x \cdot \Phi(x)$,其中 $\Phi$ 是高斯累积分布函数。

PIM友好的近似: \(GELU(x) \approx 0.5x\left(1 + \tanh\left[\sqrt{\frac{2}{\pi}}\left(x + 0.044715x^3\right)\right]\right)\)

分解为PIM操作:

  1. 计算 $x^3$:两次乘法
  2. 线性组合:$y = x + 0.044715x^3$
  3. 缩放:$z = 0.7978845y$
  4. Tanh查表:$t = \tanh(z)$
  5. 最终计算:$0.5x(1+t)$

4. Softmax的分布式计算

Softmax需要全局归一化:$y_i = \frac{e^{x_i}}{\sum_j e^{x_j}}$

PIM分布式实现:

Step 1: 各Bank计算局部最大值
max_local[bank] = max(x[bank_start:bank_end])

Step 2: 全局归约得到最大值
max_global = max(max_local[:])

Step 3: 计算稳定的指数(避免溢出)
exp_x[i] = exp(x[i] - max_global)

Step 4: 局部求和
sum_local[bank] = sum(exp_x[bank_start:bank_end])

Step 5: 全局归约
sum_global = sum(sum_local[:])

Step 6: 归一化
y[i] = exp_x[i] / sum_global

通信开销:2次全局归约,O(log(NumBanks))

9.4.4 数据布局优化

数据布局直接影响PIM的访问效率和并行度。优化目标是最大化空间局部性和Bank级并行。

1. 通道优先 vs 空间优先

两种主要布局方式:

PIM偏好分析:

卷积层:NCHW更优(通道间独立计算)
全连接层:NHWC更优(向量化操作)
深度卷积:NHWC更优(通道内计算)

转换开销: \(T_{transform} = \frac{DataSize}{Bandwidth} + N \times T_{permute}\)

2. Bank交织策略

将数据交织存储以提高并行度:

传统布局:
Bank0: A[0:1024]
Bank1: A[1024:2048]
...

交织布局:
Bank0: A[0,128,256,...]
Bank1: A[1,129,257,...]
...

交织粒度选择:

3. 稀疏数据的紧凑存储

对于稀疏张量,采用压缩格式减少存储和带宽:

COO格式(坐标格式):

values: [1.2, 3.4, 5.6, ...]
rows:   [0, 1, 1, ...]
cols:   [2, 0, 3, ...]

CSR格式的Bank映射:

Bank[i]存储第i行的非零元素
row_ptr[i]指向Bank[i]的起始位置
动态负载均衡:根据nnz(row)分配Bank

压缩率: \(CompressionRatio = \frac{1}{sparsity} \times \frac{ElementSize}{ElementSize + 2 \times IndexSize}\)

对于90%稀疏度的FP16矩阵(16-bit索引): \(CR = 10 \times \frac{16}{16 + 32} = 3.33×\)

4. 预取与双缓冲

隐藏数据传输延迟的关键技术:

Buffer A: 当前计算数据
Buffer B: 预取下一批数据

while (has_more_data):
    parallel:
        compute(Buffer A)
        prefetch(Buffer B)
    swap(Buffer A, Buffer B)

缓冲区大小优化: \(BufferSize = \max(ComputeTime, TransferTime) \times Bandwidth\)

保证计算和传输完全重叠。

5. 数据对齐与填充

PIM硬件通常要求特定的对齐:

对齐要求:64-byte(缓存行)
原始大小:1000 × 1000
填充后:1024 × 1024(2的幂次,便于地址计算)

填充开销: \(OverheadRatio = \frac{AlignedSize - OriginalSize}{OriginalSize}\)

权衡:填充开销 vs 访问效率提升

9.5 工业界案例:Samsung HBM-PIM与UPMEM

本节通过分析两个代表性的商用PIM产品,展示数字存内计算从概念到产品的技术演进。Samsung HBM-PIM代表了高端服务器市场的解决方案,而UPMEM则面向通用计算的大规模部署。

9.5.1 Samsung HBM-PIM架构分析

Samsung HBM-PIM是业界首个量产的HBM集成PIM解决方案,于2021年正式发布。它在标准HBM2 Aquabolt基础上集成了可编程计算单元(PCU),实现了存储与计算的深度融合。

架构概览:

┌─────────────────────────────────┐
│        Host Processor           │
└─────────────┬───────────────────┘
              │ HBM Interface
┌─────────────┴───────────────────┐
│         Base Logic Die          │
│  ┌─────────────────────────┐    │
│  │  Command Processor      │    │
│  │  PIM Controller         │    │
│  │  Data Router            │    │
│  └─────────────────────────┘    │
└─────────────┬───────────────────┘
              │ TSV Array (>5000)
┌─────────────┴───────────────────┐
│         DRAM Stack              │
│  ┌──────────────────────┐       │
│  │ Bank 0 │ PCU 0       │       │
│  ├──────────────────────┤       │
│  │ Bank 1 │ PCU 1       │       │
│  ├──────────────────────┤       │
│  │  ...   │  ...        │       │
│  ├──────────────────────┤       │
│  │ Bank 15│ PCU 15      │×8层   │
│  └──────────────────────┘       │
└─────────────────────────────────┘

关键规格:

PCU微架构:

每个PCU包含:

┌──────────────────────────────┐
│      Bank Row Buffer (8KB)    │
├──────────────────────────────┤
│   Programmable MAC Unit       │
│   ┌────┬────┬────┬────┐      │
│   │MAC0│MAC1│MAC2│MAC3│ ×4   │
│   └────┴────┴────┴────┘      │
├──────────────────────────────┤
│   Vector Register File        │
│      (16 × 256-bit)          │
├──────────────────────────────┤
│   Scalar Unit & Control       │
└──────────────────────────────┘

MAC单元特性:

编程模型:

Samsung HBM-PIM采用SIMD编程模型,所有PCU执行相同指令:

// PIM指令示例
PIM_MAC(dst, src1, src2, acc);  // MAC操作
PIM_ADD(dst, src1, src2);       // 向量加法
PIM_RELU(dst, src);             // 激活函数
PIM_LOAD(reg, addr);            // 从Bank加载
PIM_STORE(addr, reg);           // 存储到Bank

编译器自动将高层算子映射到PIM指令序列:

# PyTorch层
output = F.linear(input, weight, bias)

# 编译后的PIM代码
for i in range(0, M, TILE_M):
    for j in range(0, N, TILE_N):
        PIM_LOAD(R0, weight[i:i+TILE_M])
        PIM_LOAD(R1, input[j:j+TILE_N])
        PIM_MAC(R2, R0, R1, R2)
        PIM_ADD(R2, R2, bias)
        PIM_RELU(R2, R2)
        PIM_STORE(output[i,j], R2)

性能优化技术:

  1. Bank级流水线:
    时刻t:   Bank0执行计算
    时刻t+1: Bank0写回,Bank1执行计算
    时刻t+2: Bank1写回,Bank2执行计算
    
  2. 数据预取机制:
    • 硬件预取器识别访问模式
    • 提前将数据加载到row buffer
    • 隐藏DRAM访问延迟
  3. 稀疏加速:
    • 零值检测单元
    • 跳过零权重的MAC操作
    • 稀疏度50%时加速1.8×

9.5.2 UPMEM DPU设计

UPMEM是首个商用的通用型PIM处理器,采用标准DDR4 DIMM封装,可直接插入现有服务器。每个DIMM包含多个DPU(DRAM Processing Unit),实现真正的大规模并行计算。

DPU架构:

┌─────────────────────────┐
│    DPU Core (32-bit)    │
│  ┌──────────────────┐   │
│  │  24 GP Registers │   │
│  │  Condition Codes │   │
│  │  Program Counter │   │
│  └──────────────────┘   │
├─────────────────────────┤
│   14-stage Pipeline     │
│  - Fetch (2 stages)     │
│  - Decode (2 stages)    │
│  - Execute (8 stages)   │
│  - Writeback (2 stages) │
├─────────────────────────┤
│    24KB IRAM            │
│    (Instruction RAM)    │
├─────────────────────────┤
│    64KB WRAM            │
│    (Working RAM)        │
├─────────────────────────┤
│    64MB MRAM            │
│    (Main RAM - DRAM)    │
└─────────────────────────┘

关键特性:

三级存储层次:

  1. WRAM(工作内存):
    • 64KB SRAM
    • 单周期访问
    • 用于频繁访问的数据
  2. MRAM(主内存):
    • 64MB DRAM
    • ~100周期访问延迟
    • DMA传输到WRAM
  3. IRAM(指令内存):
    • 24KB专用指令存储
    • 支持循环缓冲优化

编程接口:

UPMEM提供C语言SDK和运行时API:

// Host端代码
#include <dpu.h>

struct dpu_set_t dpu_set;
DPU_ASSERT(dpu_alloc(NR_DPUS, NULL, &dpu_set));

// 加载程序到DPU
DPU_ASSERT(dpu_load(dpu_set, DPU_BINARY, NULL));

// 广播数据到所有DPU
DPU_FOREACH(dpu_set, dpu) {
    DPU_ASSERT(dpu_copy_to(dpu, "input_data", 0, 
                          &input[dpu_id], size));
}

// 启动DPU执行
DPU_ASSERT(dpu_launch(dpu_set, DPU_SYNCHRONOUS));

// 收集结果
DPU_FOREACH(dpu_set, dpu) {
    DPU_ASSERT(dpu_copy_from(dpu, "output_data", 0,
                            &output[dpu_id], size));
}

DPU端核心代码:

// DPU端代码
#include <mram.h>
#include <perfcounter.h>

__mram_noinit uint8_t input_data[INPUT_SIZE];
__mram_noinit uint8_t output_data[OUTPUT_SIZE];

int main() {
    // 从MRAM加载到WRAM
    mram_read(input_data, wram_buffer, size);
    
    // 执行计算
    for (int i = 0; i < size; i++) {
        result[i] = process(wram_buffer[i]);
    }
    
    // 写回MRAM
    mram_write(result, output_data, size);
    
    return 0;
}

性能优化策略:

  1. WRAM管理:
    • 双缓冲技术
    • 软件流水线
    • 数据预取
  2. DPU间通信:
    • 通过host中转
    • 批量同步减少开销
    • 局部归约优化
  3. 负载均衡:
    • 静态任务划分
    • 工作窃取机制
    • 动态重分配

9.5.3 性能与功耗评估

Samsung HBM-PIM性能分析:

在实际AI工作负载上的表现:

工作负载 传统HBM HBM-PIM 加速比 能效提升
BERT-Base 100ms 35ms 2.86× 2.3×
ResNet-50 15ms 8ms 1.88× 1.6×
LSTM 120ms 28ms 4.29× 3.8×
Recommendation 80ms 18ms 4.44× 4.1×

性能提升来源分析:

功耗分解(20W总功耗):

DRAM刷新:    3W (15%)
DRAM访问:    5W (25%)
PIM计算:     8W (40%)
控制逻辑:    2W (10%)
I/O接口:     2W (10%)

UPMEM DPU性能评估:

基准测试结果(256 DPU系统):

应用类型 CPU基线 UPMEM 加速比 能效比
基因组分析 1.0× 12.5× 12.5× 8.7×
数据库Join 1.0× 3.8× 3.8× 15.2×
图遍历 1.0× 5.2× 5.2× 10.1×
稀疏矩阵 1.0× 7.6× 7.6× 12.3×

扩展性分析:

DPU数量  吞吐量   效率
1        1.0×     100%
16       15.2×    95%
64       58.8×    92%
256      225×     88%
1024     860×     84%

对比分析:

特性 Samsung HBM-PIM UPMEM DPU
目标市场 AI加速 通用计算
集成度 高(HBM内) 中(DDR4)
编程模型 SIMD MIMD
单位算力
灵活性
部署成本

9.5.4 应用场景与局限性

Samsung HBM-PIM适用场景:

  1. 推荐系统:
    • 大规模embedding查表
    • 稀疏特征交叉
    • 内存带宽密集
  2. 自然语言处理:
    • Attention计算
    • 大词表softmax
    • Beam search
  3. 科学计算:
    • 稀疏线性代数
    • 图神经网络
    • 分子动力学模拟

UPMEM DPU适用场景:

  1. 数据库加速:
    • 并行扫描
    • Hash join
    • 聚合操作
  2. 生物信息学:
    • 序列比对
    • 基因组装
    • 变异检测
  3. 数据分析:
    • 时间序列处理
    • 模式匹配
    • 数据压缩

技术局限性:

  1. 编程复杂性:
    • 需要重写算法
    • 数据布局优化困难
    • 调试工具不完善
  2. 硬件约束:
    • 固定的计算能力
    • 有限的局部存储
    • 缺乏浮点支持(部分产品)
  3. 生态系统:
    • 软件栈不成熟
    • 缺乏标准化接口
    • 有限的框架支持
  4. 成本效益:
    • 初期投资高
    • 需要专门优化
    • ROI周期长

未来发展方向:

  1. 标准化:
    • 统一编程模型
    • 标准化接口(如CXL)
    • 开放生态系统
  2. 架构演进:
    • 支持更复杂运算
    • 改进互连架构
    • 集成专用加速器
  3. 软件优化:
    • 自动并行化编译器
    • 高层抽象框架
    • 性能分析工具
  4. 应用拓展:
    • 边缘AI推理
    • 实时分析
    • 新兴工作负载

9.6 高级话题:近数据计算的缓存一致性

9.6.1 缓存一致性协议挑战

9.6.2 PIM感知的缓存管理

9.6.3 虚拟内存与地址转换

9.6.4 多核PIM系统的同步机制

本章小结

练习题

常见陷阱与错误

最佳实践检查清单