图优化
最近在整理之前的一些工作内容, 记录下来温故而知新
在各种开源推理框架中,我们总能看到有一种graph optimizer技术,主要是对用户想要运行的网络模型进行一种网络结构层面的优化,剔除不需要的Op、融合某些特定的相邻Op、转换某些框架不支持或者实现效率较低的Op等。但是目前网上貌似系统的介绍图优化方向的文章较少,本文是在整理了目前几个开源框架MNN、NCNN、ONNX-Runtime中关于图优化技术后所完成,希望能让大家对图优化有一个大略的了解。
前言
- 本文着重介绍是图优化,对于本文出现的Op的定义不作介绍.这些Op名可能是来自于各种框架
- 手画的示意图中矩形代表Op,矩形右边的一般为Op的参数信息,圆形代表tensor。字丑请见谅
- 一些图优化的实现是取决于推理框架自身的Op实现情况,并不是说一种推理框架的图优化就一定能用在另外一个推理框架上
- 每个图优化操作后面都标了来源框架,具体实现可参考下属源代码链接:MNN图优化源代码1、MNN图优化源代码2、NCNN图优化源代码、ONNX-Runtime图优化源代码
- 整理过程以MNN为主,然后在NCNN和ONNX-Runtime中补充MNN没有的操作
正文
Eliminations删除
-
Op本身无意义
有些Op本身不参与计算,在推理阶段可以直接去掉对结果没有影响
-
RemoveUnusefulOp(MNN)
包括Seq2Out,“Identity”, “NoOp”, “Print”, “Assert”, “StopGradient”, caffe的Split, Cast转换前后类型相等或者是int32、int64, Concat并且只有输入一个tensor
-
RemoveDropout(MNN)
dropout无需多言了吧
-
eliminate_noop(NCNN)
noop是NCNN中定义的forward为空的一种Op
-
Op参数无意义
有些Op本身是有意义的,但是设置成某些参数后就变成了无意义的了
-
TensorConverterSameMerge(MNN)
TensorConverter是MNN里用于转换数据排布格式的Op,当参数src等于dst时该Op无意义可被删除
-
Slice Elimination(ONNX-Runtime)
当Slice Op的index_start等于0、index_end等于c-1时该Op无意义可被删除
-
Expand_Elimination(ONNX-Runtime)
Expand Op指定的输出shape等于输入shape时该Op无意义可被删除
-
eliminate_pooling1x1(NCNN)
1x1的pooling无需多言了吧
-
Op位置无意义
一些Op在一些特殊的位置会变得多余无意义
-
RemoveOutputTensorConvert(MNN)
模型的输出不需要进行内存排布转换
-
Unsqueeze Elimination(ONNX-Runtime)
当Unsqueeze Op的输入是const Op时,可以将const Op进行Unsqueeze操作后直接删除Unsqueeze Op
-
eliminate_orphaned_memorydata(NCNN)
NCNN里的memorydata就是const Op,当没有其他Op将该const Op作为输入时可认为其为“孤儿”orphaned,可删除
-
eliminate_reshape_before_binaryop(NCNN)
TODO:
-
eliminate_reshape_after_global_pooling(NCNN)
这里的reshape是flatten,即期望reshape后的tensor的w=1,h=1,c=c,而global_pooling本身输出tensor就是w=1,h=1,c=c,因此可删除reshape
-
eliminate_flatten_after_global_pooling(NCNN)
同上
-
eliminate_flatten_after_innerproduct(NCNN)
innerproduct就是全连接层,输出tensor在NCNN里也是w=1,h=1,c=c,因此后续的flatten可删除
-
Op前后重复
前后两个相邻的Op都是同一类时,可能只需要一个
-
Op前后反义
前后两个相邻的Op进行的操作时相反的时候这两个Op都可以删除
-
EliminateSqueezeExpandDims(MNN)
Squeeze和ExpandDims这两个Op是反义的,一个压缩维度,一个是拓展维度,当连续的这两个Op指定的axis相等时即可同时删除这两个Op
-
RemoveInverseTensorConverter(MNN)
当连续的两个内存排布转换Op的参数前后反义,即src1等于dst2,可同时删除这两个Op
-
EliminateQuantAndDequant(MNN)
连续进行量化和反量化,可同时删除这两个Op
-
Concat_Slice_Elimination(ONNX-Runtime)
合并后又进行同样的拆分,可同时删除这两个Op
-
公共子图
- Common_Subexpression_Elimination(ONNX-Runtime)
当模型当中出现了公共子图,如一个输出是另外两个同类型同参数的Op的输入,则可进行删除其中一个Op.Onnx的实现说实话我没太看懂。但是理解起来和实现起来都不难。我自己实现了一版。同时这是一个经典的算法题目,公共子树,有兴趣可自行搜索
Fuse融合
Transformer转换
思考
对模型利用上述操作逐一进行图优化的过程中,个人觉得应该是个do while的过程,即对于原始模型net进行一遍全部的图优化后得到net2,比较net和net2是否相等,如果不相等则再进行一次循环。这么做是因为可能后进行的图优化操作引入了新的可优化点,只进行一次的话可能会遗漏。但是貌似MNN的图优化流程就只是进行一次. 但是需要注意do while的操作可能某两个图优化操作会引入死循环, net和net2始终不相等.
图优化的意义是很大的, 但是可做的方向并不是很多, 就是以上列举的几类, 基本是通用的一些点加上一些跟各自框架本身定义Op实现有关的点. 所以感觉这就是图优化没有成为模型推理加速的研究热门方向的原因吧. 还有哪些遗漏的图优化操作欢迎大家补充
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)