1. 项目背景与核心价值
通用矩阵乘法(GEMM)作为深度神经网络(DNN)中最耗时的计算操作,占据了卷积层和全连接层90%以上的计算量。传统GEMM加速器通常采用脉动阵列架构,通过数据流优化实现高能效计算。然而,随着模型压缩技术的发展,权重剪枝产生的稀疏性为GEMM计算带来了新的优化空间——如何高效处理稀疏矩阵成为加速器设计的关键挑战。
FlexiSAGA的创新之处在于其架构灵活性。它支持7种数据流模式(3种密集+4种稀疏),包括经典的输出驻留(OS)、权重驻留(WS)和输入驻留(IS)策略,并专门针对稀疏矩阵设计了压缩稀疏块(CSB)格式。这种设计使得在AlexNet、VGG16等典型DNN上实现了1.41-4.28倍的稀疏加速比,显著优于商用CPU/GPU平台。
关键突破:FlexiSAGA首次实现了在单一架构上动态切换多种数据流模式,并能根据矩阵稀疏特性自动选择最优计算路径。这种灵活性使其在边缘设备部署场景中具有独特优势。
2. 脉动阵列架构深度解析
2.1 基础架构设计
FlexiSAGA的核心是一个可配置的二维脉动阵列(Systolic Array),其行列数可根据需求调整。每个处理单元(PE)包含:
- 9个可配置位宽的寄存器文件
- 支持浮点和整数运算的ALU
- 相邻PE间的数据通路(右向和下向)
阵列外围分布着三类关键单元:
- 加载单元(LU):位于左侧和上侧,负责将数据从主存加载到PE
- 存储单元(SU):位于右侧和下侧,负责将结果写回主存
- 解压缩单元(DecU):作为内存访问仲裁器,处理稀疏矩阵的零值跳过
这种设计实现了计算与数据移动的重叠,通过数据流式传输最大化硬件利用率。实测显示,16×16阵列相比4×4配置可获得约2.1倍的加速,而面积仅增加约3.8倍。
2.2 数据流模式对比
| 数据流类型 | 驻留数据 | 流动数据 | 适用场景 | 带宽需求 |
|---|---|---|---|---|
| dOS(密集输出驻留) | 输出部分和 | 权重+输入 | 小批量推理 | 高 |
| dWS(密集权重驻留) | 权重 | 输入+部分和 | 权重复用率高时 | 中 |
| dIS(密集输入驻留) | 输入 | 权重+部分和 | 输入复用率高时 | 中 |
| sOS(稀疏输出驻留) | 输出部分和 | 压缩权重+输入 | 高稀疏权重 | 低 |
| csOS(CSB输出驻留) | 输出部分和 | CSB压缩权重+输入 | 非均匀稀疏 | 最低 |
实际测试发现,在AlexNet的卷积层中,csOS模式相比传统dOS可减少达73%的内存访问量。这是因为CSB格式通过列合并技术,将原本需要多次加载的稀疏列合并为单次加载。
3. 稀疏计算关键技术
3.1 稀疏矩阵压缩格式
FlexiSAGA支持两种创新的稀疏存储格式:
两阶段位图格式:
- 列位图:标记存在非零元素的列(1bit/列)
- 元素位图:标记每列中的非零元素(1bit/元素)
- 值数组:连续存储所有非零值
对于128×512的矩阵,在80%稀疏度下,该格式仅需原始数据37%的存储空间。
压缩稀疏块(CSB)格式:
- 列索引数组:记录非零列的位置
- 合并计数器:记录合并的列数
- 值数组:存储合并后的非零值
CSB的核心创新在于列合并算法:
def merge_columns(columns): merged = [] for col in columns: found = False for m in merged: if can_merge(m, col): # 检查零元素位置是否互补 m.merge(col) found = True break if not found: merged.append(col) return merged这种格式特别适合处理非均匀稀疏模式,在GoogLeNet的某些层中实现了100倍加速。
3.2 稀疏计算数据流实现
以sOS(稀疏输出驻留)模式为例,其计算流程分为三个阶段:
初始化阶段:
- 控制器读取列位图,跳过全零列
- 非零列的权重通过LU加载到左侧PE列
- 对应输入行加载到顶部PE行
计算阶段:
// PE内部处理逻辑 always @(posedge clk) begin if (valid_in) begin partial_sum <= partial_sum + weight * input; // 向右传播输入,向下传播权重 out_right <= input; out_down <= weight; end end写回阶段:
- 底部和右侧PE将结果通过SU写回
- 控制器更新输出矩阵指针
实测显示,这种设计使得在VGG16的FC层处理中,稀疏路径比密集路径节省了58%的时钟周期。
4. 硬件感知的模型剪枝
4.1 结构化剪枝算法
FlexiSAGA采用基于L2范数的结构化剪枝:
- 将CONV层通过im2col转换为矩阵
- 按PE阵列尺寸分块(如8×8)
- 对每个块按行/列计算L2范数
- 剪除范数最小的s%行/列向量
算法关键参数:
- 初始稀疏度s=70%
- 每次递增δ=1%
- 精度损失上限ε=2%
经验提示:当PE阵列为矩形时(如4×16),应选择与短边对齐的向量方向。实测显示,对16×4阵列采用列向剪枝比行向剪枝快1.7倍。
4.2 剪枝效果分析
不同网络的最终稀疏度:
| 网络 | 平均稀疏度 | 最高稀疏层 | 加速比 |
|---|---|---|---|
| AlexNet | 82% | fc6(91%) | 4.28× |
| VGG16 | 79% | conv5_3(88%) | 3.17× |
| ResNet50 | 68% | block4_2(76%) | 1.41× |
特殊发现:当向量长度n与PE阵列维度匹配时(如8×8阵列用n=8),可获得最佳性能。这是因为硬件能更高效地处理对齐的数据块。
5. 性能优化实战技巧
5.1 设计空间探索方法
通过虚拟原型进行参数扫描:
- 固定PE总数(如72个)
- 枚举所有因数分解(4×18,6×12,...)
- 对每种配置测试7种数据流
- 结合不同剪枝参数(n=1,4,8,16)
在AlexNet上的发现:
- CONV层:6×12阵列+sOS最优
- FC层:12×6阵列+csOS最优
- 全局最优:4×18阵列(内存带宽利用率最高)
避坑指南:避免使用正方形阵列(如8×8),矩形设计通常能更好地平衡计算和IO。实测显示4×18比8×8快23%。
5.2 典型问题排查
问题1:加速比低于预期
- 检查项:剪枝方向是否与阵列长边垂直
- 案例:16×4阵列应采用行向剪枝(n=16)
问题2:精度下降过大
- 解决方案:调整ε从2%到1%,增加微调epoch
- 数据:VGG16在ε=1%时top-1仅降0.4%
问题3:内存带宽瓶颈
- 优化手段:采用CSB格式+csOS数据流
- 效果:ResNet50带宽需求降低61%
6. 对比实验与部署建议
6.1 平台对比数据
| 平台 | AlexNet加速比 | 能效(TOPS/W) |
|---|---|---|
| Intel Xeon(48线程) | 1.8× | 0.7 |
| Nvidia Orin GPU | 2.0× | 5.2 |
| FlexiSAGA 16×16 | 4.3× | 14.7 |
注:测试条件为同等2%精度损失,batch=1
6.2 边缘部署策略
模型转换流程:
- PyTorch模型 → 结构化剪枝 → CSB格式转换
- 生成配置文件(数据流选择映射表)
资源分配建议:
- 小模型(<1MB权重):4×4阵列
- 中等模型:8×8阵列
- 大模型:16×16阵列+分块处理
实时性保障:
- 对关键层采用WS数据流(确定性延迟)
- 非关键层用OS数据流(最大化吞吐)
在实际车载视觉系统中,采用8×8配置的FlexiSAGA实现了60fps的ResNet50推理,功耗仅1.2W。这主要得益于csOS数据流将DDR访问频率降低了78%,使得系统可以工作在更低电压下。