数据流与脉动阵列:脉动阵列基础、行静态数据流与数据复用策略

各位同学,今天我们进入Eyeriss架构最核心的部分——数据流与脉动阵列。说实话,这部分内容我当年啃时也花了不少时间。但一旦搞懂了,你会发现它其实很优雅。

2.1 脉动阵列基础

脉动阵列(Systolic Array)这个名字,听起来挺唬人。说白了,它就是一种让数据像心跳一样,有节奏地在处理单元(PE)之间流动的架构。

我习惯把脉动阵列想象成一条流水线。每个PE只做两件事:计算和传递。它从邻居那里拿到数据,算完一部分,再把结果传给下一个PE。

核心特征:

  • 局部通信:每个PE只和相邻的PE交换数据,没有全局总线瓶颈
  • 规则化:所有PE执行相同的操作,只是数据不同
  • 高吞吐:数据像流水一样持续流入,每个时钟周期都能产生结果

举个例子,一个经典的1D脉动阵列做矩阵乘法。假设我们要计算 C = A × B。A矩阵的每一行从左往右流,B矩阵的每一列从上往下流。每个PE内部做乘累加(MAC)操作。数据每拍移动一次,就像心脏搏动一样规律。

我在项目中遇到过一个问题:脉动阵列的规模一旦做大,数据加载就成了瓶颈。你想想看,如果阵列是256×256,一次就要加载65536个权重。怎么喂得饱?这就引出了数据复用策略。

2.2 行静态数据流(Row-Stationary)

Eyeriss最让我佩服的设计,就是提出了行静态(Row-Stationary, RS)数据流。它和传统的脉动阵列思路完全不同。

传统脉动阵列里,数据是流动的,权重也是流动的。但RS数据流的核心思想是:让权重待在PE里不动,只让输入特征图和部分和流动。

为什么会这样?我解释一下。卷积运算中,同一个卷积核的权重会被反复使用。如果权重在PE里固定下来,就不用每次都从全局缓存里读。这能省下大量带宽和功耗。

我的经验: 在Eyeriss的RS数据流中,每个PE负责计算输出特征图的一个行片段。权重加载一次后,就在PE内部“驻扎”下来,直到该行片段计算完毕。这有点像你在工位上干活,工具就放在手边,不用每次去仓库取。

具体来说,RS数据流把卷积计算分解成三个维度:

  • 行方向:每个PE处理输出特征图的一行
  • 列方向:多个PE并行处理不同的输出通道
  • 深度方向:输入通道的累加在PE内部完成

我曾经踩过一个坑:一开始我以为RS数据流就是简单的“权重不动,数据动”。但实际实现时发现,部分和(partial sum)的传递路径才是关键。如果部分和传递顺序搞反了,会导致严重的流水线停顿。

下面这张图展示了RS数据流的核心逻辑:

行静态数据流(Row-Stationary)核心逻辑 输入特征图 权重加载 PE 阵列(3×3 示例) PE(0,0) 权重固定 PE(0,1) 权重固定 PE(0,2) 权重固定 PE(1,0) 权重固定 PE(1,1) 权重固定 PE(1,2) 权重固定 部分和传递 输出特征图 关键点: 1. 权重加载到PE后固定不动,减少全局带宽消耗 2. 输入特征图在PE间水平传递,部分和在PE间垂直累加 3. 每个PE只负责输出特征图的一个行片段,降低PE间通信量

2.3 数据复用策略

数据复用,说白了就是让同一份数据被多个PE重复使用,避免重复从DRAM里读。在Eyeriss中,数据复用分为三个层次:

复用层次 复用对象 复用方式 节省带宽
权重复用 卷积核权重 同一权重被多个输入通道共享 高
输入特征图复用 输入像素 同一像素被多个卷积核窗口共享 中
部分和复用 中间累加结果 部分和在PE间传递,避免重复计算 低(但减少计算量)

我建议你重点关注权重复用。在卷积神经网络中,权重的数据量往往最大。如果能把它留在PE里,效果立竿见影。

避坑指南: 我曾经在设计一个加速器时,过度追求输入特征图的复用,结果导致PE阵列的利用率很低。后来发现,权重复用才是大头。因为权重的重用次数 = 输出特征图的高度 × 宽度,而输入特征图的重用次数 = 卷积核大小。对于3×3卷积,输入复用只有9次,而权重复用可能是几百次。所以,优先优化权重复用。

在RS数据流中,数据复用的具体实现是这样的:

  1. 权重复用:每个PE加载一个权重行,然后固定不动。该PE处理完所有输入通道后,再加载下一行权重。
  2. 输入特征图复用:同一行输入特征图在PE阵列中水平广播,被多个PE同时使用。
  3. 部分和复用:垂直方向上的PE通过累加链传递部分和,每个PE只做一次加法,结果传给下一个PE。

嗯,这里要注意:三种复用策略不是孤立的。它们需要协同工作。我习惯用“空间映射”这个词来描述这种协同。简单说,就是把卷积循环(比如输出通道、输入通道、空间位置)映射到PE阵列的物理维度上。

举个例子,假设PE阵列为4×4,卷积核大小为3×3,输出通道数为16。RS数据流会这样映射:

  • 4个PE处理同一输出通道的不同空间位置(行方向)
  • 4个PE处理不同的输出通道(列方向)
  • 每个PE内部累加3×3=9个输入通道

这样,权重在PE内固定了9个周期,输入特征图在行方向复用了4次,部分和在列方向累加了4次。三种复用同时发生,效率很高。

我的小技巧: 在设计数据流时,先画一张时空图。横轴是PE的物理位置,纵轴是时间。把每个PE在每个时钟周期做什么标出来。这样能直观地看到数据复用是否充分,有没有空闲的PE。我每次做架构评估,第一件事就是画时空图。

最后,总结一下RS数据流相比传统脉动阵列的优势:

对比维度 传统脉动阵列 RS数据流
权重移动 权重在PE间流动 权重固定在PE内
数据复用 主要复用输入特征图 权重、输入、部分和三者复用
带宽需求 高(权重频繁加载) 低(权重一次加载多次使用)
PE利用率 受限于数据供应 高(数据流设计匹配计算模式)

好了,这一章的内容就到这里。RS数据流是Eyeriss的灵魂,理解了它,后面讲稀疏计算时你会觉得顺理成章。