3. 数据流与计算模式:NPU上的数据流模型
大家好,我是你们的老朋友。今天我们来聊聊NPU上最核心的话题之一——数据流与计算模式。
说实话,很多做AI加速的工程师,一开始都容易忽略数据流的重要性。大家总觉得,把算力堆上去就行了。但我在项目中踩过不少坑,最后发现:数据怎么搬、怎么存、怎么复用,往往决定了你芯片的真实性能。你想想看,算力再高,数据喂不进去,那也是白搭。
3.1 三种经典的数据流模型
NPU里的数据流模型,说白了就是决定“谁待在原地不动,谁来回移动”。我习惯把这个问题想成是工厂流水线:你是让工人(计算单元)不动,物料(数据)送过来?还是让物料不动,工人走过去?
目前业界公认的三种模型是:Input Stationary(输入驻留)、Weight Stationary(权重驻留)、Output Stationary(输出驻留)。咱们一个一个来看。
3.1.1 Input Stationary(输入驻留)
这种模式下,输入特征图(Input Feature Map)被固定在计算单元里。权重数据流过来,跟输入做乘加运算。我个人比较喜欢这种模式,因为输入数据往往比较大,搬来搬去太费带宽。
我在做某个图像分类模型时,发现输入特征图的复用次数很高。用Input Stationary,可以把输入数据一次性加载到本地缓存,然后反复使用。这样,权重虽然要频繁加载,但权重本身数据量小,带宽压力不大。
优点:
- 输入数据复用率高,减少DRAM访问
- 适合输入通道数多的卷积层
缺点:
- 权重需要频繁加载,对权重压缩有要求
- 输出部分累加结果需要临时存储
3.1.2 Weight Stationary(权重驻留)
这个模式正好反过来。权重数据固定在计算单元里,输入特征图流式加载。嗯,这里要注意:权重的复用次数通常等于batch size。如果你的batch size很大,这种模式就很香。
我曾经在部署一个BERT模型时,batch size设到了64。用Weight Stationary,权重只加载一次,然后所有batch的输入数据依次流过。效果非常好,带宽利用率直接拉满。
3.1.3 Output Stationary(输出驻留)
这种模式下,输出结果(Partial Sum)被固定在计算单元里。输入和权重都流式加载,计算结果不断累加到本地。
说实话,这种模式我用的不多。但它有一个独特的优势:减少输出数据的写回次数。如果你的输出特征图很大,写回DRAM会成为瓶颈,那Output Stationary就派上用场了。
三种模型对比:
| 模型 | 驻留数据 | 流式数据 | 适用场景 |
|---|---|---|---|
| Input Stationary | 输入特征图 | 权重 | 输入通道多、输入复用率高 |
| Weight Stationary | 权重 | 输入特征图 | batch size大、权重复用率高 |
| Output Stationary | 输出部分和 | 输入+权重 | 输出特征图大、写回带宽受限 |
3.2 数据复用策略
数据复用,说白了就是让同一份数据被尽可能多的计算单元使用。你想想看,从DRAM搬一次数据要花多少能量?比一次乘加运算多两个数量级!所以,复用策略做得好,能效直接翻倍。
我总结了几种常见的复用策略:
- 空间复用:同一份数据广播给多个PE(处理单元)。比如权重广播,所有PE同时用同一份权重计算不同的输入。
- 时间复用:同一份数据在不同时间被同一个PE使用。比如输入数据在本地缓存里待着,多个时钟周期反复使用。
- 混合复用:空间+时间一起上。这是最常用的策略,也是NPU设计的难点。
3.3 脉动阵列(Systolic Array)的工作原理
脉动阵列,这个名字听起来很玄乎。其实说白了,就是让数据像心跳一样,有节奏地在计算单元之间流动。每个PE只做一件事:接收数据,做乘加,然后把结果传给下一个PE。
Google的TPU就是脉动阵列的典型代表。我记得第一次看TPU论文时,被它的简洁设计震撼到了。没有复杂的控制逻辑,数据流就像流水一样自然。
脉动阵列的核心特点:
- 规则化:所有PE结构相同,布局规整
- 局部通信:数据只跟相邻PE交换,没有全局连线
- 流水线:数据像流水一样,每个时钟周期向前推进
下面我画了一张图,帮你理解脉动阵列的数据流动过程:
你看这张图,权重从左往右流,输入数据从上往下流。每个PE收到数据后,做一次乘加,然后把部分和(Psum)往下传。最终,右下角的PE22输出完整的计算结果。
这种设计的好处是什么?局部性极强。每个PE只跟邻居通信,没有全局连线。时钟频率可以跑得很高,功耗也低。我当年第一次在FPGA上实现脉动阵列时,看到数据真的像心跳一样有节奏地流动,那种感觉,嗯,很爽。
3.4 实际项目中的选择
说了这么多,到底怎么选?我个人的经验是:没有银弹。
我在做某个视频分析芯片时,试过好几种方案。最后发现,对于卷积层,Input Stationary配合脉动阵列效果最好。但对于全连接层,Weight Stationary更合适。所以,现代NPU基本都是混合架构——不同层用不同的数据流模型。
嗯,这里还要提醒一点:编译器要跟硬件配合。你硬件支持了三种数据流模型,编译器得能自动选择最优的映射方案。否则,再好的硬件也发挥不出性能。
好了,数据流和计算模式就聊到这里。记住一句话:数据怎么流动,决定了你的NPU能跑多快。下一章我们聊聊更具体的缓存优化策略,到时候见。
想要更多资料,联系可可