第二讲:片上存储架构——SRAM与寄存器文件设计、多Bank交叉存储、存储分区策略
各位同学,今天我们聊聊片上存储。说白了,就是芯片内部那些“小仓库”怎么设计。
我做了十几年芯片,最深的体会是:存储子系统往往是整个AI芯片的瓶颈。计算单元再快,数据喂不进去,一切都是白搭。今天这堂课,我把自己踩过的坑、积累的经验,都摊开来跟你们讲讲。
2.1 SRAM vs 寄存器文件:选型与设计
先问个问题:SRAM和寄存器文件,到底有什么区别?
很多人觉得,不都是存数据的吗?嗯,对,但也不全对。
SRAM(静态随机存取存储器),我习惯叫它“大仓库”。容量大,密度高,但访问速度相对慢一些。一个典型的SRAM宏单元,6T结构,面积小,功耗低。
寄存器文件(Register File, RF),我管它叫“快取手边”。容量小,但速度极快。通常用D触发器或锁存器搭建,读写延迟可以做到1个时钟周期以内。
我在项目中遇到过这样一个场景:某AI加速器需要频繁读取权重参数。一开始我全用SRAM,结果发现每次读取都要等2-3个周期,流水线经常断流。后来我把最常访问的几百个参数放到寄存器文件里,性能直接提升了15%。
来看一个简单的对比表:
| 特性 | SRAM | 寄存器文件 |
|---|---|---|
| 存储单元 | 6T SRAM cell | D触发器 / 锁存器 |
| 容量 | 几KB ~ 几十MB | 几十 ~ 几百个entry |
| 读延迟 | 2~3 cycles | 1 cycle |
| 面积效率 | 高 | 低 |
| 典型用途 | 权重缓存、特征图缓存 | 标量寄存器、地址生成器 |
2.2 多Bank交叉存储:让带宽翻倍
好,接下来讲一个我特别喜欢的技巧——多Bank交叉存储。
为什么需要它?你想想看,一个SRAM只有一个读写端口。如果多个计算单元同时要访问它,那就得排队。排队就意味着等待,等待就意味着性能损失。
解决办法?把一个大SRAM拆成多个小Bank。每个Bank都有自己的读写端口。这样,多个访问请求可以并行处理。
我曾经设计过一个4Bank交叉存储的权重缓存。原本单Bank的带宽是256bit/cycle,拆成4个Bank后,理论带宽变成了1Kbit/cycle。当然,实际没那么理想,因为存在Bank冲突——两个请求同时打到同一个Bank上。但通过合理的地址映射,冲突率可以控制在5%以内。
来看一个简单的地址映射示例:
// 假设有4个Bank,每个Bank 256行
// 地址格式: [行地址(8bit)] [Bank选择(2bit)] [字节偏移(2bit)]
// 访问地址 0x00A4:
// 行地址 = 0x29 (41)
// Bank选择 = 0x01 (Bank 1)
// 字节偏移 = 0x00
// 连续访问 0x00A4, 0x00A8, 0x00AC, 0x00B0
// 分别落在 Bank 1, Bank 2, Bank 3, Bank 0
// 完美并行!
2.3 存储分区策略:让数据各归其位
最后聊聊存储分区。这个策略说白了就是:把不同类型、不同生命周期的数据,放到不同的存储区域里。
为什么要分区?我举个例子。AI芯片里通常有三类数据:
- 权重参数:只读,生命周期长(整个推理过程不变)
- 输入特征图:只读一次,生命周期短
- 中间结果:读写频繁,生命周期极短
如果把它们混在一起存,会怎样?
嗯,我踩过这个坑。有一次设计一个卷积加速器,我把所有数据都塞进同一个SRAM里。结果发现:权重读取和中间结果写入频繁冲突,导致带宽利用率不到40%。
后来我做了分区:
- 权重区:专用SRAM,只读端口,支持多Bank交叉
- 输入区:双端口SRAM,一读一写,支持行缓冲
- 中间结果区:寄存器文件 + 小容量SRAM,低延迟优先
分区之后,带宽利用率提升到了85%以上。
2.4 知识体系总览
为了让大家更直观地理解,我画了一张图:
这张图把今天的内容串起来了。从SRAM和寄存器文件的选型,到多Bank交叉存储的拆分,再到存储分区的策略,每一步都是为了一个目标:让数据流动更顺畅,让计算单元不空等。
好了,今天就讲到这里。这些内容都是我实际项目中反复验证过的。你们回去可以想想:如果让你设计一个AI芯片的存储子系统,你会怎么选?怎么拆?怎么分区?
公众号:蓝海资料掘金营,微信deep3321