文档章节

揭开神经网络加速器的神秘面纱之DianNao

_夜枫
 _夜枫
发布于 2017/07/04 14:33
字数 2873
阅读 31
收藏 0

原文链接

 

1 前言

1.1 挖坑(写在前面的废话,可以直接忽略)

 

最近开始负责组里神经网络加速器IP的开发,暂时还是基于FPGA实现,因此阅读了一些经典的神经网络加速器实现的论文,包括基于ASIC的寒武纪系列,TPU系列,以及一些基于FPGA的,打算写一个专题,专门介绍各个神经网络芯片的实现细节。

1.2 广告(不适者可以直接忽略)

在具体介绍之前,先表明一下个人观点:基于神经网络的专用加速芯片应该是一个大趋势,但是在业务量还没稳定之前,FPGA还是有很大发展潜力的。最后,硬件只是整个神经网络加速器系统中最简单的一个环境,算法和软件才是最复杂的,所以也欢迎在这个领域有想法的兄弟部门一起来合作,我们提高底层FPGA和FPGA上的实现能力,算法大神们提供算法解决方案,软件大神们提供系统解决方案,一起把这个事情做起来。

2 DianNao

2.1 背景

DianNao是中科院计算所陈老师寒武纪系列的开山之作,奠定了陈老师在这个领域里的地位;文章主要内容从今天的视角来看,还是比较简单的,因此今天我们先来聊聊DianNao。

首先要说明的是,DianNao绝不是神经网络加速器的第一个实现,在DianNao这片文章的相关工作部分就介绍了很多已有的设计,但是DianNao和之前这些实现比起来有一个最大的不同:之前文章的重点都集中在如何高效实现计算部分。这很容易理解,神经网络加速器本来不就是用来加速神经网络计算的嘛。但是当你的模型参数越来越大时,你没有办法把所有参数都保存在片内了,这个时候访存必然会成为你的瓶颈,因此DianNao这篇文章选择高效实现访存作为切入点!

2.2 整体架构

几乎所有的神经网络加速芯片都有如下共性的模块:

  1. 一个计算单元,主要完成深度学习中矩阵乘/卷积操作;这个计算单元的实现大致分为两种: 1. 以TPU为代表的脉动阵列(systoic array); 2. 点乘器(dot-product)。

  2. 片上存储单元,存储每一层的输入filter map/输出filter map及权值(weights):目前的设计中,输入 filter map和输出 filter map一般都是共享一块片上存储资源;权值(weights)可以很大,因此有时候不能全部存储在片上;

 

其实神经网络加速芯片这两个共性的模块一点也不难理解,神经网络加速芯片不就是为了完成每个网络层的计算嘛,因此需要一个高吞吐量的计算单元;为了能喂饱这个计算单元,就必须想办法高效的给其喂数据,因此就有了片上存储单元。具体到DianNao这个芯片,我们来看看其内部实现:

111.png

对应上面这个架构图,我们来具体分析一下这块芯片。首先来看一下计算单元。

1 计算单元NFU

DianNao中计算单元称之为NFU(Neuron Function Unit),这是一个典型的点乘器(dot-product)方案,可以看到这个NFU分了三个阶段,分别为: 负责做乘法的NFU-1;负责做累加的NFU-2;及负责做激活函数的NFU-3。上面这个架构图看起来可能不太直观,我单独把这个模块功能分解一下,重新画了一副图:

222.png

上图是DianNao整体架构图中红框内容展开,一个这个结构计算输出output feature map中一个点.不同的是,在DianNao里,一共有16个输入I0 - I16 和16个权值W0 - W16做点积,这里为了方便,只画了8个input的点积。注意在NFU-2最后的阶段有一个寄存器R(图中红框里的字母R表示),这是用来存储中间结果的,只有当一个卷积/全链接层中一个点计算完后,才会进行激活操作,而中间阶段部分和会临时存在寄存器R中;另外最后一个加法器还有一个输出是不经过NFU-3,直接输出的(图中蓝色虚线表示),这是因为有一些层计算没有激活这个操作,典型的如池化层;对应均值池化,只需要设置好对应权值,NFU-2的输出就是池化的输出结果,如:对于一个kernel大小为2x2的均值池化层,只需要把权值设置为1/4,NFU-2的输出就是池化的结果。最后需要说明,为了支持最大值池化,这里的加法器其实除了需要支持加法功能,还必须支持比较功能。

在DianNao的设计中,上述这个结构一共有16个,因此可以同时计算16个输出output feature map中的点。具体深度学习中各个层怎么映射到上述这个结构中的,后面会有详细介绍。

2 片上存储单元

在DianNao整体架构中,除了NFU模块,另外一个重要的模块就是三块片上存储单元了:

  1. NBin: 保存每一层的输入数据;位宽Tn表示Tn个半精度浮点数,因为DianNao采用的是半精度fp16数据计算,因此位宽Tn表示Tn个fp16;
  2. NBout: 保存每一层的输出数据;位宽同样用Tn表示;
  3. SB: 保存模型的权值,位宽为Tn X Tn

对于每一层,整个数据流为: NFU从NBin读取input feature map,从SB读取weight,然后计算,最终得到的结果存在NBout中。这里有个问题,那就是每次计算完一层,都需要把NBout buffer里数据copy会NBin,对于现在的设计,基本都会将NBin和NBout合并成一个buffer,利用地址区分输入和输出。

3 其他模块

  1. DMA引擎:可以看到每个片上存储单元都有一个DMA引擎,可以独立的和主存DDR交换数据;
  2. Control Processor(CP): 这个是整个芯片的控制逻辑,DianNao采用了比较简单的指令系统,利用一个简单指令译码单元,可以将指令转换成控制单元里面信号的高低。

4 总结

可以看到,整个DianNao的硬件结构还是比较简单的,至于一个神经网络模型到底是怎么样在这个简单的硬件上执行起来的,就要靠软件在处理输入数据,去控制各个模块的工作,因此,同硬件相比,软件的工作量更大!

3 具体案例

在这部分,我将简单介绍一下,各个层是如何在DianNao里工作的,重点介绍全链接层;这里其实有一套简单的指令系统,但是为了介绍的更具体一些,我就直接举例子来说明了,对指令系统感兴趣的可以自己去读论文。

3.1 全链接层+激活层(sigmoid)

1 参数介绍

  1. 全链接层的输入是8192个神经元,输出是256个神经元;
  2. 片上存储单元的位宽Tn为16;因此NBin位宽为16个FP16,为16x16-bit;NBout也为16x16-bit;SB为256x16-bit;
  3. 片上存储单元NBin的深度为64;因此NBin大小为2KB( 64项 X 256 bit)。NBout也为64项,因此NBout大小也为2KB;SB也为64项,因此SB大小为32KB,

2 全链接层介绍

全链接层的本质是一个向量和一个矩阵相乘,得到一个向量。具体到这个case,那就是一个 1 x 8192的向量 I (公式1)和一个8192 x 256 的矩阵W(公式2)相乘,得到一个 1 x 256 的向量O(公式3)。

111

3 具体实现

  1. 数据重用 (reuse)

对于每一个输出矩阵O中的点,其都需要8192个I作为输入,因此输入向量I中每个点,在计算不同的输出点时,是可以重用的,这样可以减少对DDR的访问;对于权值O,不具备这个特性

  1. 数据传输

因为NBin一次只能容纳 64 x 16个输入,而总共有8192个输入,因此必须分成8个tile;对于SB,总共有8192x256个权值,但是一次只能容纳 64x256个,因此需要分为128个tile。

input feature map第一个tile在NBin中排列如下:

222

weight第一个tile在SB中排列如下:

333

  1. 具体计算过程
  2. load input filter map第一个tile到NBin;
  3. load weight第一个tile到SB;
  4. read NBin一项,这16个input 同时输入给16个点乘器(每个点乘器输入为16个input 和16个weight),每个点乘器的input feature输入相同
  5. read SB一项256个weight分别输入给16个点乘器(16个点乘器,每个需要16个weight作为输入),每个点乘器的weight均不同;
  6. 计算这16个输出filter map的部分和,并和临时寄存器R相加,并将结果保存在临时寄存器R中;
  7. 重复上述操作64次,可以得到输出16个filter map点的部分和;这时候其实对于输出,只计算了1024个输入点的部分和,因此这个结果还只是一个中间结果。这时如果要继续计算这16个output点,那就必须更新NBin,达不到input reuse目地,因此我们选择把这个中间结果写入到NBout中;然后开始计算下一组output点的部分和。
  8. load下一组weight进入SB(这里其实用到了double buffer,在第一组weight计算同时,第二组weight以及在load了),重复利用NBin数据。重复上述步骤,经过16次后,在NBout中得到256个输出点前1024个输入点的加权和。
  9. 同时更新NBin和SB内容;NBin load下一个input feature map的下一个tile。这时注意一定要从NBout中read出来对应output点的中间结果,存到临时寄存器R中。
  10. 上述步骤重复8次,inpute feature map的8个tile均计算完成,得到最终的全链接层输出。注意在计算得到最终结果的那轮NFU运算里,才会触发NFU-3这个pipeline,执行激活函数,其他时间里,NFU-3阶段均被pypass。

3.2 卷积层+激活层(sigmoid)

最简单的,卷积运算可以转换乘矩阵乘,后续过程就类似全链接层的运算了。

 

 

原文链接

 

本文转载自:http://click.aliyun.com/m/24918/  

_夜枫
粉丝 10
博文 506
码字总数 0
作品 0
朝阳
后端工程师
私信 提问
DianNao系列加速器总结(1)——架构与运算单元

本文为DianNao系列加速器总结的第一篇,有较多公式,简书不支持公式渲染,公示完整版待该总结完成后将统一发表在个人博客 简介 DianNao系列是中科院计算所推出的系列机器学习加速器,包括以下...

月见樽
2018/05/01
0
0
Opera在2009美国CES上发布最新SDK

1月7日,全球知名浏览器开发商挪威Opera软件公司在2009年美国电子展揭开了Opera SDK 9.7的神秘面纱.2008年,Opera投入了大量的资源开发Opera SDK 9.7,并与合作伙伴紧密合作,以加速浏览器在各种...

红薯
2009/01/08
135
0
揭开tomcat神秘的面纱之bootstrap启动2

在上文揭开tomcat神秘的面纱之bootstrap加载1中,本菜鸟分析道了context的启动就嘎然而止,是因为的启动过程最复杂,现在来分析context的启动过程。 是一个webApp,所有相关Context的启动都在...

一滴水的坚持
2018/11/25
0
0
揭开tomcat神秘的面纱之bootstrap加载

在上文揭开tomcat神秘的面纱之bootstrap初始化中,本菜鸟分析了bootstrap最终会经过初始化,加载,启动三个步骤。接着来分析加载过程。 加载过程如下: 在加载过程中,实质是利用反射,调用的...

一滴水的坚持
2018/11/05
0
0
CDN Tengine开源技术沙龙

Tengine开源项目从阿里集团内部核心HTTP服务器,到其层流量统一入口核心系统,再到阿里云CDN节点系统七层负载接入,一路走来积攒了大量一线开发调试经验并逐步实现工具化。作为阿里集团七层流...

我是王雪梨
2018/05/09
27
4

没有更多内容

加载失败,请刷新页面

加载更多

PCB设计-Allegro软件入门系列-铺铜操作(下)

铺铜是PCB很常见的操作,PCB的敷铜一般都是覆地铜,增大地线面积,有利于地线阻抗降低,使电源和信号传输稳定,在高频的信号线附近敷铜,可大大减少电磁辐射干扰,起屏蔽作用。 本讲讲解啊一...

demyar
8分钟前
1
0
如何通过WASI SDK 在Linux上编译ZXing C++

Mozilla在今年三月份的时候公布了WASI。WASI的目标就是让WebAssembly在任何地方都可以运行,而不仅仅像现在这样只能运行在Node.js和Web浏览器中。WASI目前依然处于初级阶段,这篇文章分享下如...

yushulx
9分钟前
1
0
.Net界面开发神器—DevExpress官方汉化包免费下载!还在等什么?

点击获取DevExpress v19.1.7新版试用下载 DevExpress Localization Service允许您创建一组自定义的附属程序集,要将语言包添加到程序集中,请查看本文中为大家列出的对应版本的汉化包,下载并...

FILA6666
10分钟前
2
0
php生成二维码

        header('Content-Type: image/png');        //清除缓冲区,防止之前面不知道的情况下被加头部信息导致不显示图片内容        ob_clean();        $...

横着走的螃蟹
15分钟前
2
0
伪类和伪元素

伪类和伪元素 伪类和伪元素,对于绝大多数同学来说,都是耳熟能详的名字,但确实又有很多人搞不清楚它们之间的区别,以致于混淆概念。而当概念都混淆的时候,也往往意味着你不会经常使用它,...

不负好时光
17分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部