FireFly:一种利用DSP和内存优化加速SNN的硬件加速器设计

背景

读 FireFly: A High-Throughput Hardware Accelerator for Spiking Neural Networks With Efficient DSP and Memory Optimization

硬件加速器包括直接在GPU上使用CUDA进行加速计算,亦或者使用FPGA设计电路,最终得到成熟的ASIC设计。使用FPGA进行加速相比于GPU会具备更高的能效比(帧率/功耗 或 算力/功耗),由于SNN天然具备稀疏性,这使得使用FPGA来设计SNN的加速器可以获得更高的能效比。本文的主要贡献可以被划分为

1.使用DSP设计PE脉动阵列,使用SIMD来加速DSP计算(减少了逻辑资源占用)。

2.设计了一套通用型硬件加速器。

3.对权重的缓存即部分重用FIFO很有特点。

设计流程

通过高级综合语言(Hign-Level Synthesis/Scala/Chisel)或直接使用verilog描述电路,同时使用FPGA芯片集成的一些DSP资源来加速计算,组成硬件加速器设计。文章中讲是使用的scala + SpinalHDL。这同样是一种高级综合语言。

设计目的

在FPGA上部署神经网络,仅使用片上存储虽然会带来很大的速度提升,但片上存储资源的大小也会限制网络。另外,SNN的计算与ANN不同,不需要复杂乘法,因此大多数工作都是直接使用RTL描述这一过程。FireFly利用DSP资源完成了这一过程,在内存方面,设计了一个形似ping-pang RAM + FIFO 的 部分重用FIFO(partial reuse FIFO)来提升外部存储访问速度。

Methods

图1

整体结构如图1,首先设计结构属于通用型硬件加速器,主要的计算逻辑都在PL端完成,通过Weight Delivery Hierchy和Linebuffer for Conv两个模块将计算需要的权重以及特征加载进PE单元进行计算,其中数据同步在AXI DataMover完成,通过地址线控制。计算完成后,配置了可选的Maxpool模块,网络中不需要时可以旁路。最后数据通过AXI总线再次送回DDR以供PS端调配。

PS端主要起到控制整体运算的作用,笔者推测PS端没有复杂逻辑,但DDR中的地址是和PL端有一套固定的协议的。不管PL端从其中取数计算,计算后存储等都是通过这套协议完成。

下面对其中主要的两个创新点进行分析:

部分重用FIFO

图2

文章首先给出了经典的乒乓RAM和FIFO的设计(a,b),其次给出了部分重用FIFO的设计(c)。乒乓RAM由于其深度不同,最少需要两倍于输入缓存的空间。FIFO由于先入先出,需要的空间不固定。不管是乒乓RAM或者FIFO,都需要输入输出两边的数据速率匹配,否则会存在被压爆的情况。图c的部分重用FIFO中,不仅有FIFO的输入输出指针,还多了一块重用空间,用Start和End来标识,当重用数据进入时,会存储进这块空间,在计算若干次后,重置这块空间。

隐藏数据传输延迟以提高吞吐量

图3

图3即图1中描述的Weight Delivery Hierchy。其中Lv1通过位宽放大将每拍1个数据转换成每8拍8个数据送入部分重用FIFO,其中有些数据会被送入重用空间,在这之后,数据以每拍8个数据输出,(笔者不清楚这里速率不匹配是否因为重用数据使用多次导致)。在之后再通过位宽放大至每8拍8x8个数据输出。文章使用这样的结构提前加载权重来隐藏了冗长的权重读取时间(从DDR过AXI总线到PE单元)。

利用DSP设计的特殊PE单元

图4

图4中(d)即图1的PE阵列,其中单个PE单元是通过串行8个DSP资源完成的。单个DSP资源的使用方式笔者也查阅了Xilinx的文档,其中支持了一种单指令多数据流的方式。

图5(图片来源Xilinx文档)

其中SIMD模式即将AB合起来(48bit)与C(48bit)进行加法计算,由于使用了SIMD,因此计算会被拆分成4个12bit和4个12bit之间的加法,输出也是4个12bit,进位会被输出到一个进位端口。FireFly一文在权重量化中选择8bit。因此DSP计算在不级联时不会进位(8+1 bit),最大级联16个时会产生进位。因此文章选择了长度8的级联方式。8bit+log2(8)+1 = 12,刚好不进位。

回到图4(c),使用SIMD将权重合并,利用输入脉冲作为驱动OPMODE(SIMD的端口使能)的信号,完成权重间加法运算,从而实现加速。

FireFly一文并没有过多提及如何利用这些8x8的PE单元来对应网络中某一块计算,也没有提及 部分重用FIFO 的重用数据如何划分的。笔者认为这些还是值得探讨的。

结论

使用DSP而不是直接使用LUT+FF的确减少了逻辑资源,但实际上LUT资源一般是够用的。需要特别节省的是内部的存储资源。

文章最后比对了资源使用和吞吐率。由于使用了DSP而不是LUT,可以看出LUT同比其他设计有明显减少。

最后,文章评估了在不同数据集下的准确率来验证设计的正确性,以及评估了功耗,其中2.55W的功耗非常亮眼。

  • 15
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用蜣螂算法优化LSTM超参数的Python代码: ```python import random import numpy as np import math import tensorflow as tf from sklearn.datasets import load_iris from sklearn.preprocessing import MinMaxScaler # 加载数据集 iris = load_iris() X = iris.data y = iris.target # 归一化数据 scaler = MinMaxScaler() X = scaler.fit_transform(X) # 设置LSTM网络结构 def lstm_model(n_input, n_hidden, n_classes): inputs = tf.keras.layers.Input(shape=(n_input, 1)) x = tf.keras.layers.LSTM(n_hidden, activation='tanh', return_sequences=True)(inputs) x = tf.keras.layers.LSTM(n_hidden, activation='tanh')(x) outputs = tf.keras.layers.Dense(n_classes, activation='softmax')(x) model = tf.keras.models.Model(inputs=inputs, outputs=outputs) return model # 计算模型的损失函数和准确率 def model_eval(model, X, y): y_pred = model.predict(X) y_pred = np.argmax(y_pred, axis=1) accuracy = np.mean(y_pred == y) loss = tf.keras.losses.sparse_categorical_crossentropy(y, y_pred) return accuracy, loss # 定义蜣螂算法 def firefly_algorithm(X, y, n_input, n_hidden, n_classes, max_generation, alpha=0.5, betamin=0.2, gamma=1.0): # 初始化火蝗 n_fireflies = 20 fireflies = [] for i in range(n_fireflies): n_hidden_layer = random.randint(8, 128) learning_rate = 10 ** random.uniform(-5, -2) model = lstm_model(n_input, n_hidden_layer, n_classes) accuracy, loss = model_eval(model, X, y) fireflies.append({'model': model, 'accuracy': accuracy, 'loss': loss, 'n_hidden_layer': n_hidden_layer, 'learning_rate': learning_rate}) # 开始迭代 for t in range(max_generation): # 计算每个火蝗的亮度 for i in range(n_fireflies): for j in range(n_fireflies): if fireflies[i]['accuracy'] < fireflies[j]['accuracy']: r = sum([(fireflies[i]['model'].get_weights()[k] - fireflies[j]['model'].get_weights()[k]) ** 2 for k in range(6)]) beta = betamin * math.exp(-gamma * r ** 2) # 移动火蝗 new_model_weights = [] for k in range(6): new_weight = fireflies[i]['model'].get_weights()[k] * (1 - beta) + fireflies[j]['model'].get_weights()[k] * beta + alpha * np.random.uniform(-1, 1, size=fireflies[i]['model'].get_weights()[k].shape) new_model_weights.append(new_weight) new_model = lstm_model(n_input, fireflies[i]['n_hidden_layer'], n_classes) new_model.set_weights(new_model_weights) new_accuracy, new_loss = model_eval(new_model, X, y) # 更新火蝗的亮度 if new_accuracy >= fireflies[i]['accuracy']: fireflies[i]['model'] = new_model fireflies[i]['accuracy'] = new_accuracy fireflies[i]['loss'] = new_loss # 找到最优的模型 best_model = None best_accuracy = -1 for i in range(n_fireflies): if fireflies[i]['accuracy'] > best_accuracy: best_model = fireflies[i]['model'] best_accuracy = fireflies[i]['accuracy'] return best_model, best_accuracy # 调用蜣螂算法进行优化 best_model, best_accuracy = firefly_algorithm(X, y, n_input=X.shape[1], n_hidden=64, n_classes=len(np.unique(y)), max_generation=50) # 输出结果 print('Best accuracy:', best_accuracy) print('Best model:', best_model.summary()) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值