查看原文
其他

TVM: Deep Learning模型的优化编译器(强烈推荐, 附踩坑记录)

阿莱克西斯 极市平台 2021-09-20

加入极市专业CV交流群,与6000+来自腾讯,华为,百度,北大,清华,中科院等名企名校视觉开发者互动交流!更有机会与李开复老师等大牛群内互动!

同时提供每月大咖直播分享、真实项目需求对接、干货资讯汇总,行业技术交流点击文末“阅读原文”立刻申请入群~


作者 | 阿莱克西斯

来源 | https://zhuanlan.zhihu.com/p/58918363

作者按:前排提醒,本文的人文内容部分稍稍带有艺术加工,请保持一定的幽默感进行阅读


本来可能用不到TVM,项目其实进展的很顺利,我们初始的tensorflow模型在android端得到了满意的latency,我也可以照常一边修炼我的仙,继续和有奶大定律, 自由单子, Kan-Extension等邪魔外道搏斗...一边稳稳的推进项目进度。


无奈scientist一意孤行要上Pytorch, 于是我们换了一个Pytorch模型...


先不说同样的SSD魔改模型,Pytorch在android端比tensorflow整整慢了5倍,光是把Pytorch模型移植到Android上都让开发团队整整褪层皮(Pytorch对Android的支持简直为0,tensorflow的工程支持相对pytorch简直无敌)。而这时候已经花了好多时间,项目眼看要delay....


头都炸了的我在打算手撸OpenCL调优之前,去问了下我们组的CV大神该怎么办,大神微微一笑,转身随风而去,只听云端传来3个字:“T~V~M~~~~~"


于是我就开始TVM的研究(踩坑)之路, 到今天为止终于把所有的路都踩平了之后,成功把我们的Pytorch模型用Auto-TVM调优成功且部署在了我们的android系统上,性能整整提高了8倍,比我们之前的tensorflow模型还要快。更重要的是,通过TVM,我们的调优完全不couple与硬件和模型Framework,就算以后换模型,换终端,或者哪天scientist想不开要换回tensorflow或是使用MXNet都无所谓,用auto-TVM自动调调就行了(只可惜了我的Cuda C编程调优都白学了)。


简单介绍下Auto-TVM的调优终端设备的用法



  1. 你可以有很多手机平板设备,安装好TVM RPC这个App之后,可以在App里输入Tracker的IP和端口,进行设备注册(另外输入一个设备ID来让Auto-TVM tuning程序找到)。

  2. Tracker是一个Python的程序,git clone TVM之后,按教程编译好,就可以按这个教程:https://github.com/dmlc/tvm/tree/master/apps/android_rpc启动Tracker。

  3. Auto-TVM tuning程序也是一个python程序,它会连接Tracker(也可以和Tracker是一台机器)找到相应的设备ID的IP,然后和设备直接用RPC通信,Auto-TVM程序会根据程序预设的target(比如是不是arm cpu,要不要用OpenCL...) 来把你想要优化的Deep Learning模型直接编译为设备的machine code, 通过TVM RPC把code部署在终端,终端的TVM RPC App会测试这个模型的inference performance,然后回报给Auto-TVM tuning程序,然后Auto-TVM tuning程序会根据反馈,重新计算该如何优化编译,重新生成新的模型的machine code再次部署... 如此循环... 直到达到预设的实验次数(比如2000), 或太多次实验都没有提高提前结束(比如第一次就找到了最优优化结果)。最后TVM会根据调优时得到的最佳“编译参数”来最终编译你的deep learning 模型为终端模型的machine code,最终完成优化编译过程。


以上只是简单介绍,具体请看TVM的论文,和去TVM官网看 tutorial,写得非常详细切提供了很多很好理解的范例代码。我的最终的tuning程序,就是魔改其中一个范例程序而来。


TVM踩坑记录

TVM目前还只是0.6版本,很多东西还不稳定,由于开发环境各异,有时候需要工程师自己解决一些开发团队在开发时没有碰到的问题,但是这些问题相对与TVM提供的巨大优势相比,都是小问题啦(工程能力越强,魔改力越强,你就可以越早体验新技术带来的好处呀。)。(我遇到的最坑的问题其实是公司网络各种IP禁止访问,封端口,使得android机和开发服务器一直连不上, 最终还是在自己的电脑上装了虚拟机,自建了一个小LAN才解决的这个问题)


1. 编译tvm4j-core出错: cannot find symbol [ERROR] symbol: class SharedSecrets


JDK11会遇到这个问题,因为JDK11已经把sun.misc.SharedSecrets换到别的地方了,建议不要尝试修改TVM源代码来fix这个问题,因为你会遇到其他更多问题,请下载JDK8,把JAVA_HOME设为JDK8的,一切就会很顺利


2. Android TVM RPC编译出错: #error "Unable to determine endianness of your machine; use CMake to compile"


https://discuss.tvm.ai/t/android-rpc-server-fails-to-build/1461


按上边link里的修改endian.h文件即可,参见我下边的修改

diff --git a/include/dmlc/endian.h b/include/dmlc/endian.hindex 5bf53fb..9422fce 100644--- a/include/dmlc/endian.h+++ b/include/dmlc/endian.h@@ -23,7 +23,9 @@ #elif defined(__EMSCRIPTEN__) #define DMLC_LITTLE_ENDIAN 1 #else- #error "Unable to determine endianness of your machine; use CMake to compile"+ #include <endian.h>+ #define DMLC_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN)+ /*!#error "Unable to determine endianness of your machine; use CMake to compile" */ #endif #endif


3. Auto-TVM运行时出错"Do not know how to handle return type code 113"


https://discuss.tvm.ai/t/auto-tvm-failed-on-android-device-with-error-msg-of-do-not-know-how-to-handle-return-type-code-113/1808


可以根据我上边在TVM Discussion里的自问自答来解决。


4. 找不到TVM_NDK_CC


https://discuss.tvm.ai/t/solved-android-rpc-test-py-failed/1339


按照dayanandasiet的回复设定TVM_NDK_CC即可

Follow the below steps to generate toolchian and try to generate application with below export command
Tool chain generate with below instruction
./make-standalone-toolchain.sh --platform=android-24 --use-llvm --arch=arm64 --install-dir=/home/user/software/android-toolchain-arm64/
Download Java and SDK, set proper path
export TVM_NDK_CC=/home/user/software/android-toolchain-arm64/bin/aarch64-linux-android-g++
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export ANDROID_HOME=/home/user/software/android-sdk-linux
build mxnet model with nnvm with below config/parameter and use same library, param and graph on your android application
target = “llvm -target=arm64-linux-android”
target_host = None
reference 
mobile_darknet_save.py 2
Compile application android deploy 1 using this config.mk 2 configuration for CPU flavor


5. LLVM only Large Small are allowd on AArch64

https://github.com/dmlc/tvm/issues/2005 可解。


6. Auto-TVM自动优化时出错:Cannot find config for target=cuda


https://discuss.tvm.ai/t/what-does-this-warning-cannot-find-config-for-target-cuda-mean/798/3


不是什么大问题,某operator不能调,对我来说其他的可以调就行了。。。。


7. Auto-TVM自动优化OpenCL时出错: No OpenCL platform matched given existing options


https://discuss.tvm.ai/t/no-opencl-platform-matched-given-existing-options/1848/6


也是自己问最终自己解决的,很反直觉,编译TVM的时候,选择OpenCL=OFF,就没有这个问题,选择OpenCL=ON,为终端Cross Compile OpenCL就不work了... 应该是bug.


8. Auto-TVM自动优化OpenCL时出错: CL_INVALID_WORK_GROUP_SIZE


https://discuss.tvm.ai/t/cl-invalid-work-group-size-error-after-auto-tuning-for-opencl-on-android-device/1858/10


应该是我trial number设的太小了,以至于TVM找不到一个valid的kernel,顺着这个问题,发现了CL_INVALID_WORK_GROUP_SIZE的一个undocumented的错误源,即OpenCL kernel使用过多的register file也会造成CL_INVALID_WORK_GROUP_SIZE错误,这一点在查OpenCL文档的时候是查不到的, 有点tricky。


9. Auto-TVM自动优化时Android TVM RPC Crush,一切白调。。。


目前TVM还不支持checkpoint,不过我们可以很简单的魔改measure_methods.py这个文件,把190行set_task(): 这个函数里的check remote失败直接raise RuntimeError退出程序,改成循环多次check即可,这样使得Auto-TVM一方持续等待Android程序上线,比一点网络问题,或者终端问题,就废掉之前n多个小时的auto-tuning成果要好的多。



最后感谢 @陈天奇大神为我们带来了这么方便的工具。





*延伸阅读


点击左下角阅读原文”,即可申请加入极市目标跟踪、目标检测、工业检测、人脸方向、视觉竞赛等技术交流群,更有每月大咖直播分享、真实项目需求对接、干货资讯汇总,行业技术交流,一起来让思想之光照的更远吧~


觉得有用麻烦给个在看啦~  

视频 小程序 ,轻点两下取消赞 在看 ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存