深度学习飞速发展过程中, 人们发现原有的处理器无法满足神经网络这种特定的大量计算, 大量的开始针对这一应用进行专用芯片的设计. 谷歌的张量处理单元 (Tensor Processing Unit, 后文简称 TPU) 是完成较早, 具有代表性的一类设计, 基于脉动阵列设计的矩阵计算加速单元, 可以很好的加速神经网络的计算. 本系列文章将利用公开的 TPU V1 相关资料, 对其进行一定的简化, 推测和修改, 来实际编写一个简单版本的谷歌 TPU, 以更确切的了解 TPU 的优势和局限性.
动手写一个神经网络加速器系列目录
谷歌 TPU 概述和简化
TPU 中的脉动阵列及其实现
神经网络中的归一化和池化的硬件实现
TPU 中的指令并行和数据并行
Simple TPU 的设计和性能评估
SimpleTPU 实例: 图像分类
拓展
TPU 的边界(规划中)
重新审视深度神经网络中的并行(规划中)
1. 不仅仅是硬件的 AI Inference
在 Simple TPU 的设计和性能评估中, 一个神经网络加速器的硬件雏形已经搭建完成了; 在 https://github.com/cea-wind/SimpleTPU 上 https://github.com/cea-wind/SimpleTPU 给出了相应的代码, 和 RTL 仿真结果. 在 TPU 中的脉动阵列及其实现和神经网络中的归一化和池化的硬件实现中, 针对硬件实现中的关键模块也进行了仿真分析. 但是, 最终并没有给出一个可以实际运行的例子. 这意味着, 即使将这一部分代码应用到 FPGA 上, 或者是实现在 ASIC 上后, 也只有纸面性能却并不可用.
和很多其他的硬件设计不同, 以 Xilinx 的 AI Inference 解决方案为例(即之前的深鉴科技), 用于 AI Inference 的设计需要考虑神经网络计算中的多样性, 神经网络加速器是一个软件 + 硬件的解决方案. Xilinx 叙述如下图(原始链接:).
从上往下看, 这一套解决方案包括
主流的神经网络的框架的支持, 包括 caffe,Tensorflow 和 mxnet
提供模型压缩和优化的工具, 以期在硬件上又更好的效能
提供模型量化的功能, 使得浮点模型转化为定点模型
提供了 Compiler, 将模型映射为二进制指令序列
和 Compiler 相结合的 Hardware
这意味着想真正使用之前设计的神经网络加速器 --SimpleTPU, 还需要软件的配合. 即便模型压缩不在考虑范围内, 也需要将模型量化为 int8 精度(SimpleTPU 只支持 int8 乘法), 同时利用 Compiler 生成指令序列. 受限于个人能力, 由于配套软件的缺失, 下面的例子中的量化和指令均由手工生成. 也正是由于这一原因, 网络结构会尽可能简单, 仅以保证本系列文章完整性为目的.
2. MLP 分类实例
利用 MLP 对 MNIST 数据集进行手写数字分类的网络结构定义如下
- class MLP(nn.Module):
- def __init__(self):
- super(MLP, self).__init__()
- self.hidden = nn.Linear(784,64)
- self.fc = nn.Linear(64,10)
- def forward(self, x):
- x = x.view(-1,784)
- x = self.hidden(x)
- x = self.fc(x)
- return F.log_softmax(x, dim=1)
生成指令后将其作为 SimpleTPU 的输入, 并对其进行 RTL 仿真(testbench 已经写好, 直接运行即可), 仿真结果如下图所示
前 16 张图的分类结果如下图所示
根据计算结果, 可以分析得到其效率为 84%.(去除了 13K 个用于读取图片和写回结果的时间, 实际应用中, 这一事件也会被计算时间覆盖)
LOC | Layers | Nonlinear function | Weights | Batch Size | % of Deployed |
2 | 2 FC | Relu | 5M | 512 | 16% |
作为参考, 谷歌 TPU 中的数值为(尽管 Simple TPU 效率较高, 但由于规模不同, 无法直接对比效率; 由于 SimpleTPU 完全按 TPU 设计, 实际性能不可能高于 TPU)
3. MLP 运行分析
通过仿真波形, 可以更直观的看出 SimpleTPU 的运行状态. 下图中, 读取 Weight, 乘加运算单元和 Pooling 共同工作可以反应 TPU 中的指令并行和数据并行中提到的指令并行.(由上倒下的 ap_start 分别是 MXU,POOL,LOAD WEIGHT 和 INSTR FETCH 的工作指示信号, 同时拉高代表同时工作)
观察 MXU 内部的信号, 可以看到计算过程中的数据并行(一条指令控制多组数据, 且一个周期完成多组计算).MXU 每个周期都输出 psum 取值, 一共有 32 个 psum, 计算一个 psum 需要 32 次乘加计算.
SimpleTPU 为什么不够快(效率并没有接近 100%)? 这一问题可有下面的仿真波形看出(每次 MXU 启动前后都有若干个周期没有输出有效结果)
由于每次 MXU 执行一条向量计算指令会又若干个空闲的周期(超过 64 个周期, 损失了 10% 以上的性能), 导致了 SimpleTPU 在这一个网络上性能只有 84%.MXU 在启动之前需要 32 个周期来填满整个脉动阵列, 而在输入结束后还需要 32 个周期来输出最后的结果. 当采用 HLS 编写代码是, 难以以这一控制力度来优化 MXU 的性能. 如果采用 Verilog HDL 或者 VHDL, 可以采用指令之间的流水设计来消除这一延时.
4. CNN
由于手工对神经网络进行量化和 layer 间融合以及生成指令的复杂性, 基于 CNN 的图像分类 / 分割网络的运行实例被无限期暂停了.
但是一个卷积计算的实例已经在 TPU 中的脉动阵列及其实现中给出, 证明了 SimpleTPU 计算卷积的能力.
根据 Simple TPU 的设计和性能评估给出的特性, SimpleTPU 可以高效支持绝大多数 Operator, 完成计算机视觉中的多种任务. 当然, 最大的缺陷在于 SimpleTPU 不显式支持 ResNet, 无法直接计算 residual connection 中的加法; 只能进行 channel concatenate 之后再利用一次乘加计算完成.
来源: https://www.cnblogs.com/sea-wind/p/11247937.html