3、存储层次结构:片上存储(SRAM)设计、全局缓冲区与本地寄存器、数据复用策略、带宽优化
存储,说白了就是加速器的命脉。
我见过太多团队,算力堆得高高的,结果数据喂不进去,整个芯片在那空转。你想想看,一个MAC阵列再强,如果数据搬运跟不上,那就是个摆设。所以这一章,咱们聊聊存储层次怎么搭,才能让数据流像高速公路一样顺畅。
3.1 片上存储(SRAM)设计:你的“数据粮仓”
SRAM是片上最快的存储,但也是最贵的。我个人习惯把SRAM分成三级:L1紧贴计算单元,L2做全局缓冲,L3偶尔用来存一些查表参数。
设计要点:
- 容量权衡:SRAM面积大,1MB的SRAM可能吃掉整个芯片面积的20%-30%。我建议先算好“最小工作集”——也就是一次卷积需要多少输入和权重,再乘以2作为安全余量。
- Bank划分:别搞一个大块SRAM,读写冲突会让你头疼。分成4-8个Bank,每个Bank独立读写,带宽直接翻倍。
- 位宽选择:我做过一个项目,SRAM位宽从64bit提到128bit,带宽翻倍,面积只涨了15%。这笔账划算。
核心原则:SRAM的读写带宽必须大于等于计算单元的需求带宽,否则计算单元就会“饿死”。
3.2 全局缓冲区与本地寄存器:数据搬运的“中转站”
全局缓冲区(Global Buffer)是连接DRAM和计算单元的桥梁。本地寄存器(Local Register)则是每个PE私有的“小仓库”。
全局缓冲区设计:
- 通常用SRAM实现,容量在256KB到2MB之间。
- 我建议采用双缓冲(Double Buffering)机制:一个缓冲区在加载数据,另一个在供给计算,流水线不中断。
- 地址映射要灵活,支持行/列/块三种访问模式。为什么?因为卷积的滑动窗口访问模式千奇百怪。
本地寄存器设计:
- 每个PE配16-32个寄存器,存当前计算需要的输入和权重。
- 我曾经踩过一个坑:寄存器太少,导致PE频繁从全局缓冲区取数,功耗飙升。后来把寄存器翻了一倍,性能提升30%。
- 寄存器文件(Register File)的读写端口要够,至少2读1写,不然数据搬运会卡住。
避坑指南:我曾经设计过一个加速器,全局缓冲区带宽算得刚刚好,结果发现DRAM的刷新周期会偷走带宽。嗯,后来加了10%的余量才搞定。
3.3 数据复用策略:让数据“多跑几趟”
数据复用,说白了就是让同一个数据被多个计算单元共享,减少从DRAM搬数据的次数。DRAM访问一次耗能是SRAM的100倍,你想想看这有多重要。
三种常见复用模式:
| 复用类型 | 适用场景 | 带宽节省 | 实现代价 |
|---|---|---|---|
| 输入特征图复用 | 卷积层(多个滤波器共享输入) | 高(5-10倍) | 低(增加广播逻辑) |
| 权重复用 | 全连接层(多个输入共享权重) | 中(2-5倍) | 中(增加权重缓存) |
| 部分和复用 | 深度可分离卷积 | 低(1.5-2倍) | 高(增加累加器) |
我的实践建议:
- 先做数据流分析,找出哪些数据被多次使用。
- 对于卷积层,我习惯用“输入复用”策略:把输入特征图广播到所有PE,每个PE算不同的输出通道。
- 对于全连接层,用“权重复用”:权重存在全局缓冲区,所有PE共享。
关键指标:数据复用率 = 总数据访问次数 / 实际从DRAM读取的数据量。这个值越高,你的加速器越省电。
3.4 带宽优化:别让数据成为瓶颈
带宽优化,说白了就是让数据在正确的时间出现在正确的地方。我总结了几条实战经验:
优化技巧:
- 数据预取(Prefetching):计算单元还在算当前数据时,提前把下一批数据加载到缓冲区。我建议用硬件预取器,比软件控制更稳定。
- 压缩传输:对权重做量化(比如从FP32降到INT8),带宽需求直接降到1/4。代价是精度损失,但很多场景可以接受。
- 乒乓操作(Ping-Pong):两个缓冲区交替工作,一个读一个写,带宽利用率接近100%。
- 突发传输(Burst Transfer):尽量用DRAM的突发模式,一次读一整行数据,而不是一个个读。我见过有人用单次读,带宽利用率只有20%。
注意:带宽优化不是越高越好。过高的带宽意味着更大的SRAM和更复杂的控制逻辑,面积和功耗会失控。找到那个“刚刚好”的点,才是高手。
3.5 存储层次结构总览
下面这张图,是我做加速器架构时必画的。它帮你理清数据怎么从DRAM流到PE:
这张图里,DRAM是水源,全局缓冲区是水库,PE阵列是用水户。水库的大小和输水管道(带宽)决定了用水户能不能吃饱。我每次做架构评估,都会先画这张图,然后标出每个环节的带宽和容量,瓶颈一目了然。
个人经验:有一次我设计的加速器,全局缓冲区只有512KB,结果跑ResNet-50时,数据复用率只有2倍。后来换成1MB,复用率直接到6倍,性能翻倍。嗯,有时候多花点面积在存储上,比堆算力划算得多。
好了,存储层次结构就聊到这儿。记住:数据流设计好了,你的加速器就成功了一半。