以前的神经网络几乎都是部署在云端(服务器上),设备端采集到数据通过网络发送给服务器做inference(推理),结果再通过网络返回给设备端。如今越来越多的神经网络部署在嵌入式设备端上,即inference在设备端上做。嵌入式设备的特点是算力不强、memory小。可以通过对神经网络做量化来降load和省memory,但有时可能memory还吃紧,就需要对神经网络在memory使用上做进一步优化。本文就以一维卷积神经网络为例谈谈怎么来进一步优化卷积神经网络使用的memory。

文章(卷积神经网络中一维卷积的计算过程)讲了卷积神经网络一维卷积的处理过程,可以看出卷积层的输入是一个大矩阵,输出也是一个大矩阵,保存这些矩阵是挺耗memory的。其实做卷积计算时,每次都是从输入中取出kernel size大小的数据与kernel做卷积运算,得到的是一个值,保存在卷积层的输出buffer里,输出也是下一层的输入。如果输入是卷积层kernel的大小(即是能做运算的最小size),输出是下一层的能做运算的最小size,相对于整个输入和输出的size而言,能节省不少memory。下面就讲讲怎么用这种思路来做CNN的memory优化。

假设当前层和下一层均为卷积层,stride为1,padding模式为same。当前层的输入是一个MxN的矩阵,kernel size是P,kernel count是Q,所以kernel是一个MxP的矩阵,当前层的输出是一个QxN矩阵。当前卷积层的输出就是下一卷积层的输入。下一卷积层的kernel size是J,kernel count是K,所以下一卷积层的kernel是一个QxJ的矩阵,输出是一个KxN的矩阵。示意如下图:

首先从输入矩阵中取出0~(P-1)列(共P列)放进输入buffer中,正好放满。与第一个kernel做卷积运算就得到一个值放进输出buffer中(0,0)位置。同样与第二个kernel做卷积得到的值放在输出buffer中(1,0)位置,与所有kernel做完卷积后得到是一个Q行1列的矩阵,放在输出buffer第一列上,如下图:

再将输入矩阵的第1~P列取出放进输入buffer中(即把输入buffer中每列向前移一格,0列移出buffer,第P列放在最后1列),同上面一样计算,得到的依旧是1列数值放进输出buffer的第2列中。如下图:

依次这么做下去,当输出buffer里的最后一列被填满时,就要触发下一卷积层做卷积运算,与K个kernel卷积运算后得到的是一个K行1列的值放进下一卷积层输出buffer的第一列中。如下图:

由于下一卷积层的输出buffer未满,不能触发后面的运算。又回到从输入矩阵中取数据放进当前卷积层的输入buffer中,再进行当前卷积层和下一卷积层的运算,结果放在各自的输出buffer里(如输出buffer满了就要把每列左移一格,0列移出buffer,新生成的1列数据放在最后1列)。类似的处理,直到把输入矩阵中取到最后一列,再把各个层的输入buffer全处理完,最后得到结果。

从上面的思路看出,输入和输出buffer从大矩阵变成kernel大小的小矩阵可以省不少memory。具体软件实现时,有输入层,中间各层(包括卷积层等),每一层为一个整体,要用event机制去触发下一个要处理的层。当一层处理完后要判断下一步是哪一层做处理(有可能是下一层,也有可能是当前层或上一层,还有可能是输入层等),就给那一层发event,那一层收到event后就会继续处理。示意如下图:

软件实现时还有很多细节要处理,尤其是当输入层数据取完后后面各层的处理,这里就不一一细述了。软件调试时先用不省memory的原始code生成每层的输出,保存在各自的文件里,用于做比特校验。然后对省memory的code进行调试,先从第一层开始,一层一层的调试。优化后的代码每层的输出跟优化前的输出是完全一样的才算调试完成。

嵌入式设备上卷积神经网络推理时memory的优化的更多相关文章

  1. Local Binary Convolutional Neural Networks ---卷积深度网络移植到嵌入式设备上?

    前言:今天他给大家带来一篇发表在CVPR 2017上的文章. 原文:LBCNN 原文代码:https://github.com/juefeix/lbcnn.torch 本文主要内容:把局部二值与卷积神 ...

  2. 嵌入式设备上的 Linux 系统开发

    转载:http://www.ibm.com/developerworks/cn/linux/embed/embdev/index.html   如果您刚接触嵌入式开发,那么大量可用的引导装载程序(bo ...

  3. MNIST数据集上卷积神经网络的简单实现(使用PyTorch)

    设计的CNN模型包括一个输入层,输入的是MNIST数据集中28*28*1的灰度图 两个卷积层, 第一层卷积层使用6个3*3的kernel进行filter,步长为1,填充1.这样得到的尺寸是(28+1* ...

  4. 用Qemu模拟vexpress-a9 (七) --- 嵌入式设备上安装telnet服务

    转载: http://blog.csdn.net/liuqz2009/article/details/6921789 Telnet协议是登陆远程网 络主机最简单的方法之一,只是安全性非常低.对targ ...

  5. 嵌入式设备上运行AllJoyn注意事项

    1. 交叉编译AllJoyn库.编译成功后的文件位于:alljoyn-3.3.0-src\build\linux\arm\debug\dist\目录下: 2. 程序要使用AllJoyn,必须要启动al ...

  6. 嵌入式Linux设备驱动程序:在运行时读取驱动程序状态

    嵌入式Linux设备驱动程序:在运行时读取驱动程序状态 Embedded Linux device drivers: Reading driver state at runtime 在运行时了解驱动程 ...

  7. 轻量级卷积神经网络——MobileNet

    谷歌论文题目: MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications 其他参考: CNN ...

  8. FFMPEG在嵌入式硬件上应用之 —— 基本环境搭建及编译

    前段时间在翻看电脑里面资料时,发现了以前做的在嵌入式硬件上面运行以ffmepg为基础,以嵌入式硬件解码的多媒体播放工作,发现都快忘记完了.今日得闲整理温习了一下ffmpeg在嵌入式上的运用,这里给大家 ...

  9. 在嵌入式设备中使用 JavaScript 的前景

    by Conmajia PC上的JavaScript已经发展到ECMAScript 6(ES6),马上ES10都快出来了(虽然还是草案),但是硬件上的JS却很少听说.这几年手持设备/可穿戴设备的发展非 ...

随机推荐

  1. 如何优雅的传递 stl 容器作为函数参数来实现元素插入和遍历?

    问题背景 开始正文之前,做一些背景铺垫,方便读者了解我的工程需求.我的项目是一个客户端消息分发中心,在连接上消息后台后,后台会不定时的给我推送一些消息,我再将它们转发给本机的其它桌面产品去做显示.后台 ...

  2. Unity 编辑器(移除missing)

    移除 Missing(Mono Script) ` private static void FindMissingReferences() { GameObject[] pAllObjects = ( ...

  3. 【Java基础】Java9 新特性

    Java9 新特性 模块化系统 Java 和相关生态在不断丰富的同时也越来越暴露出一些问题: Java 运行环境的膨胀和臃肿.每次 JVM 启动的时候,至少会 30-60MB 的内存加载,主要原因是 ...

  4. 魔法方法推开Python进阶学习大门

    热爱Python Python是Guido van Rossum设计出来的让使用者觉得如沐春风的一门编程语言.2020年11月12日,64岁的Python之父宣布由于退休生活太无聊,自己决定加入Mic ...

  5. 虚拟机Linux安装Oracle容器并实现局域网其他主机访问查询

    该文涉及Docker下Oracle容器的安装,主机端口的设置实现局域网内终端均能连接上Oracle数据库,图解如下: 一.关于Docker安装oracle容器可以参考下面博文: https://blo ...

  6. UVA - 387 A Puzzling Problem

    题目链接: https://vjudge.net/problem/UVA-387 思路: 非常有意思的拼图,深搜+回溯, 输出硬伤:除了第一次之外,每次先输空格,再输出结果, 以及可能给的数据拼不成4 ...

  7. [Ceoi2004]Journey

    题目描述 给出N个点,及你的出发点K. 接下来N-1行描述有关边的开始点,结束点,边长.保证图中不会有环 接下来给出数字J,代表你要走多少个点. 接下来J个数字,代表你要走过的点的编号.当然你可以自己 ...

  8. 集成 12 种协议、可于 USBC 端口的快充协议芯片IP2188

    1. 特性  支持 12 种 USB 端口快充协议  支持 USB TypeC PD2.0/PD3.0/PPS DFP 协议  支持多种充电协议(QC3.0/QC2.0,FCP,SCP, AFC,MT ...

  9. 在EXCEL中如何同时冻结行与列?

    鼠标所在的单元格的位置 ,决定了你冻结的行和列.如: 冻结第一行与第一列, 只需要将鼠标置于单元格在第二列,第二行. 点击冻结

  10. innodb锁和事物

    • InnoDB存储引擎支持行级锁,其大类可以细分为共享锁和排它锁两类• 共享锁(S):允许拥有共享锁的事务读取该行数据.当一个事务拥有一行的共享锁时,另外的事务可以在同一行数据也获得共享锁,但另外的 ...