Press "Enter" to skip to content

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

作者 |  阿莱克西斯

 

来源 |  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的调优终端设备的用法

 

 

 

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

 

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

 

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.h

 

index 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

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成果要好的多。

 

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

 

*延伸阅读

 

微软开源的深度学习模型转换工具MMdnn

 

不要只关心怎幺优化模型,这不是机器学习的全部

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注