超简单的卷积和加法融合

news2024/11/17 7:47:39

神经网络的优化除了之前提到的一些硬件优化手段(AI硬件加速拾遗)之外,还有很多图层方面的优化手段。大家好啊,我是董董灿。

而且图层方面的优化,有时效果更佳。往往一个有效的优化,甚至可以“消除”掉一个算子的存在。

这里的“消除”用的引号,是因为这个算子并未被真正消除,从整个神经网络的计算流上看,这个算法仍然存在。

只不过,它的计算过程被其他计算过程掩盖住了,像是被“消除”了。

这里介绍一种算子融合并且使用图层流水进行网络优化的方法。

先看Resnet50 中一个网络片段。关于该网络的算法原理,可以参考以前的文章长文解析Resnet50的算法原理。

下图展示的是 Resnet50 中第一个 block 结束时的图结构。

该结构中,存在卷积算子和加法算子,我们可以利用融合手段,将红框标出的两个算子融合成一个算子。

将卷积和加法融合成一个算子后,再通过指令调度,实现卷积和加法指令的 ping-pong 流水,便可以利用卷积的计算掩盖掉加法的计算。

关于ping-pong流水的概念,可以参考 AI加速(五)| 一个例子看懂流水——从指令到算法 来进行理解。

这里说一点,为什么卷积计算可以掩盖掉加法计算呢?

因为在相同的输入输出规模的情况下,由于卷积的计算是乘累加,而加法的计算是单纯地加法,因此,在绝大部分的硬件上,一般都是卷积的计算耗时要大于加法。

那怎么掩盖呢?

正常的一个卷积后面如果跟一个加法的话,它的计算流从上到下是这样的:

先计算卷积Conv,再计算加法Add。假设卷积的计算时间是 A, 加法的计算时间是 B,那么总共的耗时就是 A+B。

这很简单,大家都会算。

那如果将两个算子融合到一起,同时将一张输入图片(Feature Map)切成一半,分两次来运算。每次运算使用 ping-pong memory 来实现计算流水。

那两次计算的计算流从上到下是这个样子。

左侧 Conv 和 Add 计算前半张图,使用ping memory来计算,右侧 Conv 和 Add 计算后半张图,使用pong memory来计算。

这里说明一下:Conv 和 Conv 是不能并行的,因为一般一个硬件上,只有一个Conv 的硬件计算单元,当然,有多个的又是另外的话题了,这里暂时不考虑。

这个时候,可以看到第二行中,第一个 Add 和第二个 Conv 处在一个时间片内,同时由于使用的是不同的memory,两者可以完全并行。

两者并行完成计算,此时,Conv 就掩盖掉了左侧 Add 的时间。

而整个计算流消耗的时间便是:A/2 + A/2(掩盖掉了Add 的 B/2) + B/2 = A + B/2。

可以看到,此时整体的计算耗时已经比不进行流水时,减少了一半的加法。

那如果将图进一步切分,切成4份来进行运算呢?

那此时的计算流从上到下是这个样子:

由于第2、3、4行的 conv 分别掩盖掉了其左侧的Add 计算,因此,整个计算流所消耗的时间变成了 A + B/4。

可以看到,将图切的越小,流水起来之后,掩盖掉的加法的时间越多,剩余的加法的时间越少。

如果切的再多,加法的耗时甚至可以忽略掉了。

这种方法很简单,也很容易实现,但从硬件上来说,需要硬件满足以下条件:

  • 卷积计算单元和加法计算单元在硬件上是独立的。

  • 硬件有成熟的同步机制来完成卷积计算和加法计算的同步

为什么需要同步机制呢?因为每一个横向的时间片段中,Add 和 Conv 没有任何数据依赖,但是纵向的看,Add 的计算总是依赖于上面的 Conv 的输出。

因此,需要在每一个横向时间片段起始时,完成上一个时间片段中 Conv 计算和 Add 计算的同步。

只要硬件上满足了以上条件,软件上的切图、排流水、融合操作其实很简单。

很多深度学习编译器,如TVM提供了图融合和自动 tiling 策略,可以做到切图,并且调度指令完成流水排布。

即使编译器限于某些开发难度限制,无法自动完成融合和tiling,也可以手动写一个融合大算子出来,手动排指令流水,也不是很难的事。

总之,这种方法作为一个行之有效的融合方法,可以用在很多的神经网络性能优化中。

而且效果很出众。


深度学习加速优化,关注我,一起学习交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/390605.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue组件-$refs、$nextTick和name属性的使用

Vue组件-$refs和$nextTick使用一、获取DOM二、$refs获取组件对象三、$nextTick异步更新DOM四、组件name属性的使用一、获取DOM 通过id或ref属性获取原生DOM 在mounted生命周期 – 2种方式获取原生DOM标签 目标标签 – 添加id / ref恰当时机, 通过id / 通过ref属性 获取目标标签…

Ubuntu系统新硬盘挂载

Ubuntu系统新硬盘挂载 服务器通常会面临存储不足的问题,大部分服务器都是ubuntu系统,该篇博客浅浅记载一下在ubuntu系统上挂载新硬盘的步骤。本篇博文仅仅记载简单挂载一块新的硬盘,而没有对硬盘进行分区啥的。如果需要更加完善的教程&#…

【C++】平衡二叉搜索(AVL)树的模拟实现

一、 AVL树的概念 map、multimap、set、multiset 在其文档介绍中可以发现,这几个容器有个共同点是:其底层都是按照二叉搜索树来实现的,但是二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者接近有序,二叉搜索树…

Java文档搜索引擎总结

Java文档搜索引擎总结项目介绍项目使用的技术栈前端页面展示后端逻辑部分索引部分搜索模块部分Web模块部分项目介绍 Java文档搜索引擎项目是一个SSM项目,该项目的前端界面部分是由搜索页面和展示页面组成,后端部分索引模块(ScanAnalysis、in…

UNET 对 CARVANA 数据集的分割

目录 1. 介绍 2. UNET 网络 3. dataset 数据加载 4. utils 工具模块 4.1 get_loaders 函数 4.2 check_accuracy 函数 4.3 save_predictions_as_imgs 函数 4.4 完整代码 5. train 函数 5.1 关于导入的库文件 5.2 设置超参数 5.3 train_fn 训练一个epoch函数 5.4 m…

Redis是单线程还是多线程?Redis的10种数据类型,有哪些应用场景?

目录专栏导读一、同样是缓存,用map不行吗?二、Redis为什么是单线程的?三、Redis真的是单线程的吗?四、Redis优缺点1、优点2、缺点五、Redis常见业务场景六、Redis常见数据类型1、String2、List3、Hash4、Set5、Zset6、BitMap7、Bi…

【Java基础】30分钟Git 从入门到精通

一、 版本控制工具1、什么是版本控制系统?版本控制系统(Version Control System):是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。版本控制系统不仅可以应用于软件源代码的文本文件,而且可以对…

主成分分析(PCA)方法 和协方差 相关系数

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言1.主成分分析(PCA)方法2.算法步骤前言 主成分分析(Principal Components Analysis,PCA)是一种数据降…

Android工厂模式

工厂模式分为三种 :简单工厂模式 、工厂方法模式 、抽象工厂模式 。 目录 简单工厂模式 UML图 实现 使用场景: 优点 : 缺点: 工厂方法模式 UML图 实现 使用场景: 优点: 缺点: 抽象工厂模式 UM…

SpringCloud-负载均衡-Ribbon

文章目录1. 作用:负载均衡2. 应用实战2.1 provider-a代码2.2 provider-b代码2.3 consumer代码2.4 api工具向consumer发送请求查看对provider的调用情况3. ribbon总结3.1 Ribbon 源码核心3.2 如何实现负载均衡的呢?1. 作用:负载均衡 2. 应用实…

演唱会总是抢不到票?教你用Python制作一个自动抢票脚本

人生苦短 我用python 这个大家应该都知道吧? 是中国综合类现场娱乐票务营销平台, 业务覆盖演唱会、 话剧、音乐剧、体育赛事等领域。 如何快速抢票? 那么, 今天带大家用Python来制作一个自动抢票的脚本小程序 本文源码python安…

使用Java对稀疏数组的压缩与还原

稀疏矩阵的压缩与还原 稀疏数组中元素个数很少或者有大量的重复值,如果直接保存保存,会浪费很多空间,这时,就可以考虑对数组进行压缩存储。 先定义一个稀疏数组 //创建一个二维数组 11 * 11 int[][] array1 new int[11][11]; /…

Window 编辑、删除、新增右键菜单

关于 Window 右键菜单 右键菜单可以在注册表编辑器中新增和修改 建议先下载 registry-finder,查找速度更快! 使用管理员模式打开 registry-finder 后,点击 HKEY_CLASSES_ROOT ,修改注册表右键菜单的子路径如下表所示 类型路径…

49.在ROS中实现local planner(2)- 实现Purepersuit(纯跟踪)算法

48.在ROS中实现local planner(1)- 实现一个可以用的模板实现了一个模板,接下来我们将实现一个简单的纯跟踪控制,也就是沿着固定的路径运动,全局规划已经规划出路径点,基于该路径输出相应的控制速度 1. Pur…

Linux系列学习(三) - 进程和库文件

目录 引言: 学习: 基本命令补充: wc命令: more命令: less命令: cat ps命令: kill命令: bg命令: fg命令: 查看系统运行级别: 库文件&a…

unity UGUI系统梳理 - 常用可视化控件

作为一名合格的UI仔>.<&#xff0c;我发现很多UI很久没有使用了&#xff0c;所以我决定做一个UGUI系列博客重新梳理一下 1、Image 在没有放入图片下&#xff0c;image控件长这样 注意 我一般没交互需求的情况下都会把RaycastTarget给点掉&#xff0c;这个不单单是从提…

CAPL脚本DBLookup函数动态访问CAN 报文的属性

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

学习周报3.5

文章目录前言文献阅读摘要介绍方法总结相关性总结前言 本周阅读文献《Multi-step ahead probabilistic forecasting of multiple hydrological》&#xff0c;文献主要提出一种基于三维卷积神经网络、卷积最小门记忆神经网络和变分贝叶斯神经网络的混合深度学习模型&#xff08…

【博学谷学习记录】超强总结,用心分享|狂野大数据课程【Spark SQL函数定义】的总结分析

5.1 如何使用窗口函数 回顾: 窗口函数格式:分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])学习的相关分析函数有那些? 第一类: row_number() rank() dense_rank() ntile()第二类: 和聚合函数组合使用 sum() avg() max() min() count…

西电软件体系结构核心考点汇总(期末真题+核心考点)

文章目录前言一、历年真题二、核心考点汇总2.1 什么是软件体系架构?(软件体系结构的定义)2.2 架构风格优缺点2.3 质量属性2.4 质量评估前言 主要针对西安电子科技大学《软件体系结构》的核心考点进行汇总。 【期末期间总结资料如下】 针对西电计科院软件工程专业大三《软件体…