博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TensorFlow图优化(二)-Remapper,layout
阅读量:2172 次
发布时间:2019-05-01

本文共 2222 字,大约阅读时间需要 7 分钟。

    上回说到CreateExecutors中有两个分支进行图优化,一个执行的是GraphOptimizer父类的优化,另一个执行的是子类的图优化。上一篇介绍了父类优化中的CSE,这篇介绍一下子类优化的流程

一、优化流程

    每种优化子类继承自父类GraphOptimizer,而且与父类有完全不同的执行过程。其中MetaOptimizer虽然也是优化子类,但是并没有实现一种特定的优化,而是作为一个管理子类,统一完成其他所有子类的优化操作。

    从入口CreateExecutors函数开始,优化的时序简要描述如下:

CreateExecutors函数中调用CreateGraphs-->创建或获取GraphExecutionState实例,调用其BuildGraph方法-->调用OptimizeGraph-->调用grappler::RunMetaOptimizer-->RunMetaOptimizer函数是grappler命名空间中的一个接口方法,实例化MetaOptimizer,调用其Optimize方法-->调用OptimizeGraph-->调用InitializeOptimizers根据ConfigProto将优化子类实例化,放到vector中-->遍历vector调用所有实例的Optimize方法完成优化

    以上流程中,根据ConfigProto将子类实例化,是否启用优化可以在前端显式的配置,优化默认是否开启有个技巧,Rewrite proto中定义Toggle ,DEFAULT是0,ON是1, OFF是2,ConfigProto中没有设置,则默认是0,也就是DEFAULT,在实例化时,如果要默认开启,则判断!OFF时实例化子类,若要默认关闭,则判断是ON时实例化子类。

    遍历vector之外还有一层for循环,用来控制重复进行优化,如果没有设置,则默认重复优化两次,因为有些优化执行一遍后,计算图会发生变化,可能有些新的结构依旧可以进行优化,如果只想优化一次,那么可以在IsRunOnceOptimizer方法中加入判断。

二、Remapper优化

    这些子类中,将看过的记录一下,Remapper优化的目的是将FusedBatchNorm节点拆开,展开成由加法、乘法等节点组成的子图,目的不详,添加优化的仁兄可能通过验证发现FusedBatchNorm节点计算效率不如拆开算的快。

    实现过程很直觉,一共两步,第一步判断拆开的合法性,比如获取静态推断计算图,获取节点的输入属性,如果输入节点中有多余4个节点是const类型(如果有值就是const类型,4个节点是FusedBatchNorm的超参数);若合法,则按照规则将FusedBatchNorm节点拆成小节点添加到计算图中,FusedBatchNorm也就可以删掉了。batchnorm拆开的子图结构之前有画过,我以为有保留结果找不到了,o(╥﹏╥)o    不过将拆分的代码梳理一遍就可以画出子图,之前经过代码和图的对应,确实是一致的。

三、Layout

    这个是针对GPU的一个优化,对于支持data format属性的节点来说,在使用GPU设备时,NCHW格式计算更快,但是可能有些节点data format属性设置为NHWC,因此GPU设备在进行计算图调度前,会执行一遍图优化来进行自动转化,提升计算的效率。下边的例子是之前做的逆过来将NCHW转化为NHWC的优化,原理一致,懒得重新画图。

以卷积Conv节点为例,

 
 

 

在上图中,通过在Conv节点前后加入Transpose节点来转换输入数据,Transpose节点的作用是将Tensor的维度转换,“NCHW”对应0 1 2 3四个维度,将数据转换为“NHWC”格式,需要将输入Tensor的第1维度放在最后,这也是图中(0,2,3,1)的含义。将Conv节点的data_format属性设置为“NHWC”,以及其他相关的属性修改,对于不同类型的节点,还会有不同的个性化转换要求,需要在Conv节后点再加一个Transpose节点,以保证最终的输出与原输出完全一致。

但并非所有的节点都有data_format属性,第一次遍历图将所有具有data_format属性的节点完成转换,如果图中至少有一个节点发生了转换(即图中节点数增多),则需要第二次遍历图,对没有data_format属性的节点进行同样的转换。由于图4.10的转换方式会导致一个节点变成三个节点,这样节点数大量增加,因此需要策略来减少增加的节点,第二次遍历图的转换就可以实现节点的缩减,对没有data_format属性的节点也使用 Transpose来做转化,会出现相邻且互逆的Tranpose节点对,这样的节点对可以直接去掉,节点缩减的原理示意如下图所示。

 

 
 

 

 

上图左侧的模型,Conv节点有data_format属性,因此第一次遍历图需要将Conv节点进行转换,Add节点没有data_format属性,如果整个图都没有data_format属性节点,则图不需要第二次转换,但由于Add节点之前有Conv节点,因此需要将Add节点也进行转化,转化后的图如上图中间的模型,由于两个Transpose节点是互逆操作,因此可以在第三次遍历图时,将这种两个相连的Transpose节点全部删掉,这也就完成了图的缩减,减少了由于图转化带来的额外开销,如上图右侧的模型。

转载地址:http://vqhzb.baihongyu.com/

你可能感兴趣的文章
<stdarg.h>头文件的使用
查看>>
C++/C 宏定义(define)中# ## 的含义 宏拼接
查看>>
Git安装配置
查看>>
linux中fork()函数详解
查看>>
C语言字符、字符串操作偏僻函数总结
查看>>
Git的Patch功能
查看>>
分析C语言的声明
查看>>
TCP为什么是三次握手,为什么不是两次或者四次 && TCP四次挥手
查看>>
C结构体、C++结构体、C++类的区别
查看>>
进程和线程的概念、区别和联系
查看>>
CMake 入门实战
查看>>
绑定CPU逻辑核心的利器——taskset
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
逆序对的数量(递归+归并思想)
查看>>
数的范围(二分查找上下界)
查看>>
算法导论阅读顺序
查看>>