部署TVM Runtime
部署TVM Runtime
本文主要介绍如何在开发板上部署TVM Runtime, 在本地机器安装完整的TVM(包含了TVM Runtime以及编译功能), 并且使用一个简单的远程调用例子测试是否部署成功。本地机器使用的是Linux操作系统,开发板使用的是预装的Fedora系统。
开发板与TVM的概述
开发板
开发板(Embedded AI Development Kit),以 Arm SoC 为硬件平台,Tengine(Arm 中国周易平台)为核心的人工智能基础软件平台 AID,集成典型应用算法,所形成的 “软硬一体化”的 AI 开发套件; 专为 AI 开发者精心打造,面向边缘计算的人工智能开发套件。
硬件平台具备语音,视觉等传感器数据采集能力,适用于多场景的运动控制接口。
软件平台支持视觉处理与分析,语音识别,语义分析,SLAM 等应用和主流开源算法,满足AI 教育,算法应用开发,产品原型开发验证等需求。
软件是产品系列套件,主芯片采用具备主流性能 Arm SoC 的RK3228H,搭载 OPEN AI LAB 嵌入式 AI 开发平台 AID(包含支持异构计算库 HCL,嵌入式深度学习框架 Tengine,以及轻量级嵌入式计算机视觉加速库 BladeCV)。为 AI 应用提供简洁,高效,统一的 API 接口,加速终端 AI 产品的场景化应用落地。
TVM
TVM是一个针对CPU,GPU和专用加速器的开放式深度学习编译器堆栈,旨在缩小以算力为重点的深度学习框架与性能或效率为导向的硬件后端之间的差距。TVM提供以下主要功能:
将Keras, MXNet, PyTorch, Tensorflow, CoreML, DarkNet中的深度学习模型,编译成各种硬件后端上可部署的最小模块。
基础架构可在更多后端自动生成和优化张量运算符,同时得到更好的性能。
一些概念
• 远程设备,目标设备,本地机器
将开发板称为“远程设备(remote device)”和“目标设备(target device)”,用来执行生成的代码所编译出来的二进制可执行文件。因为远程连接开发板,目标是生成对开发板高效的代码。连接开发板的机器叫做“本地机器(local machine)”,用来实现生成代码,对代码进行优化,编译二进制可执行文件等功能。本地机器也拥有执行二进制可执行文件的功能。
• 架构
开发板使用的是ARM Cortex-A53处理器,架构为ARMv8,本地机器通常是x86架构。这两种架构使用了不同的指令集,使用不同指令集的程序不能够同时在不同的架构上运行。比如针对x86指令集编译的程序不能够ARM架构上运行,同样针对ARM指令集编译的程序不能够在x86架构上运行。TVM可以生成一份代码,将这份代码编译成x86的程序,在本地机器上进行调试;也可以将这份代码交叉编译成ARM程序,在目标设备也就是开发板上运行。
• 完整版的TVM 和 TVM Runtime
完整版的TVM支持生成代码,优化代码,编译,执行等功能;而TVM Runtime是TVM的一个部件,用来执行生成的二进制文件,其优点是能够更轻便地部署。
在开发板上编译TVM Runtime
将在开发板上编译TVM Runtime,在编译前,需要安装第三方依赖库。
安装第三方依赖库
TVM Runtime需要使用psutil这个Python库,获取系统的运行状态信息。而安装psutil前,需要安装两个软件包,让psutil能够成功地编译。
• psutil
默认的Python为Python3, 依次输入以下命令即可安装psutil.
sudo dnf install redhat-rpm-config python3-devel
sudo pip3 install psutil
如果想使用Python2,可以输入以下命令:
sudo dnf install redhat-rpm-config python-devel
sudo pip2 install psutil
安装完psutil后,就可以开始在开发板上编译TVM Runtime.
在开发板上编译TVM Runtime
在开发板的命令行界面下,下载TVM的代码:
git clone https://github.com/dmlc/tvm
Cloning into 'tvm'...
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 46164 (delta 0), reused 0 (delta 0), pack-reused 46157
Receiving objects: 100% (46164/46164), 15.88 MiB | 302.00 KiB/s, done.
Resolving deltas: 100% (31261/31261), done.
进入TVM的代码目录,并且输入git⊂mode–update−−recursive−−∈itgit⊂mode̲update--recursive--∈it,下载第三方依赖代码:
[openailab@localhost ~]$ cd tvm
[openailab@localhost tvm]$ git submodule update --recursive --init
Submodule 'dlpack' (https://github.com/dmlc/dlpack) registered for path '3rdparty/dlpack'
Submodule 'dmlc-core' (https://github.com/dmlc/dmlc-core) registered for path '3rdparty/dmlc-core'
Submodule '3rdparty/rang' (https://github.com/agauniyal/rang) registered for path '3rdparty/rang'
Cloning into '/home/openailab/tvm/3rdparty/dlpack'...
Cloning into '/home/openailab/tvm/3rdparty/dmlc-core'...
Cloning into '/home/openailab/tvm/3rdparty/rang'...
Submodule path '3rdparty/dlpack': checked out '0acb731e0e43d15deee27b66f10e4c5b4e667913'
Submodule path '3rdparty/dmlc-core': checked out '808f485387f9a03f78fa9f1159f387d0d91b7a28'
Submodule path '3rdparty/rang': checked out 'cabe04d6d6b05356fa8f9741704924788f0dd762'
(由于TVM的版本可能不同,checked out后的哈希值也可能不同)
输入make runtime -j2进行编译,数字2指用2个线程进行编译。
[openailab@localhost tvm]$ make runtime -j2
等待大概1到2分钟,出现以下提示说明编译成功:
[100%] Built target runtime
将TVM文件夹的Python目录添加到环境变量PYTHONPATH中:
[openailab@localhost tvm]$ cd ..
[openailab@localhost ~]$ vim .bashrc
在.bashrc的最后一行加入export PYTHONPATH=$PYTHONPATH:~/tvm/python
如果使用其它路径,需要对路径进行修改。
再退出编辑器,执行命令:source .bashrc,立即使用.bashrc中的设置。
在本地机器编译完整版的TVM
打开本地机器的命令行,同样需要下载TVM代码及其第三方依赖代码。
git clone https://github.com/dmlc/tvm
cd tvm
git submodule update --recursive --init
在tvm文件夹下,拷贝cmake配置并修改,然后开始编译:
cp cmake/config.cmake ./
sed -i "s/USE_LLVM OFF/USE_LLVM ON/" config.cmake # 将USE_LLVM设置为ON
make -j5 # 使用5个线程编译
执行完后没有任何错误信息,则说明编译完成。
设置TVM Python绑定的路径:
假如使用bash,在~/.bashrc的最后一行添加以下脚本(如果使用zsh, 则在~/.zshrc中添加):
export TVM_HOME=/path/to/tvm
export PYTHONPATH=$TVM_HOME/python:$TVM_HOME/topi/python:$TVM_HOME/nnvm/python:${PYTHONPATH}
将/path/to/tvm替换为TVM代码所在路径,该路径有python,topi,nnvm三个文件夹。
在本地机器安装好TVM后,可以进行以下测试:
打开Python并导入TVM模块
➜ ~ python
Python 3.7.4 (default, Jul 16 2019, 07:12:58)
[GCC 9.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tvm
>>>
没有任何错误提示,说明安装成功。
运行第一个TVM样例:交叉编译与远程过程调用(Cross Complication and RPC)
将使用TVM, 实现一个元素个数为1024的向量进行逐元素加1后,输出结果的核函数,在本地机器上进行调试,并在开发板开发板上运行。本样例来源于TVM的官方教程 - Cross Complication and RPC,对其进行稍许修改以适配开发板.
在开发板上启用TVM的RPC(远程过程调用)服务。
在开发板的命令行界面输入:python -m tvm.exec.rpc_server --host 0.0.0.0 --port=3939
3939为TVM RPC服务的端口,可以对其进行修改,注意开发板和本地机器上,其它程序都不要占用这个端口。TVM官方教程给的端口号为9090,本地机器的9090端口被占用了,修改为3939。
[openailab@localhost ~]$ python -m tvm.exec.rpc_server --host 0.0.0.0 --port=3939
INFO:root:If you are running ROCM/Metal, fork will cause compiler internal error. Try to launch with arg ```--no-fork```
INFO:RPCServer:bind to 0.0.0.0:3939
不要退出这个命令,以保持RPC服务的运行。
对本地机器进行配置
在本地机器的命令行界面,下载修改后的教程代码,并进入目录:
git clone https://github.com/wkcn/TVM_tutorials_for_EAIDK
cd TVM_tutorials_for_EAIDK
编辑config.py文件,将host和port修改为开发板的IP地址和开发板上TVM服务的端口。
假设开发板在局域网下的IP为192.168.43.33,TVM RPC的端口为3939,则将配置文件修改为下图:
因为开发板使用的是ARMv8指令集,所以LLVM的编译目标为aarch64-linux-gnu.
运行RPC例子
• 在本地机器调试
进入TVM_tutorials_for_EAIDK的目录,将cross_compilation_and_rpc.py文件中第115行的local_demo设为True,然后输入pythn cross_compilation_and_rpc.py.
➜ TVM_tutorials_for_EAIDK git:(master) ✗ python cross_compilation_and_rpc.py
1.225e-07 secs/op
命令行中将会输出核函数的实际调用时间。
• 在开发板上执行
将cross_compilation_and_rpc.py文件中第115行的local_demo设为False,然后输入python cross_compilation_and_rpc.py
TVM将会在本地机器上进行交叉编译,并将编译结果上传到开发板。开发板上的TVM RPC服务下载可执行的二进制文件,并执行,将结果返回到本地机器。
本地机器的命令行将输出核函数在开发板(目标设备)上的实际调用时间,不包含网络传输文件的时间。
➜ TVM_tutorials_for_EAIDK git:(master) ✗ python cross_compilation_and_rpc.py
4.3455e-06 secs/op
切换到开发板的命令行界面,可以看到:
INFO:RPCServer:bind to 0.0.0.0:3939
INFO:RPCServer:connection from ('192.168.43.57', 47010)
INFO:RPCServer:load_module /tmp/tmpge372920/lib.tar
INFO:RPCServer:Finish serving ('192.168.43.57', 47010)
说明开发板收到了本地机器(本地机器的IP为192.168.43.57)编译的可执行二进制文件的压缩包lib.tar,对其解包并执行模块,最终返回结果,结束服务。
这是一个TVM样例,可对TVM的例子进行分析,这些例子包括本文RPC例子,在开发板上运行一个分类模型,自动调整以生成适合开发板的代码。
部署TVM Runtime的更多相关文章
- Deep Learning部署TVM Golang运行时Runtime
Deep Learning部署TVM Golang运行时Runtime 介绍 TVM是一个开放式深度学习编译器堆栈,用于编译从不同框架到CPU,GPU或专用加速器的各种深度学习模型.TVM支持来自Te ...
- 离线部署ArcGIS Runtime for Android100.5.0
环境 系统:window 7 JDK:1.8.0_151 Maven:3.6.1 Android Studio:2.3 ArcGIS Runtime SDK for Android:100.5.0 1 ...
- TVMNN编译Compiler栈
TVMNN编译Compiler栈 内容纲要 前言 调研目标 TVM介绍 TVM源码架构 FrontEnd Relay BackEnd VTA实现原理及设计思想提炼 整体结构 VTA Hardware ...
- TVM部署和集成Deploy and Integration
TVM部署和集成Deploy and Integration 本文包含如何将TVM部署到各种平台以及如何将其与项目集成. 与传统的深度学习框架不同.TVM堆栈分为两个主要组件: TVM编译器,完成所有 ...
- 使用Apache TVM将机器学习编译为WASM和WebGPU
使用Apache TVM将机器学习编译为WASM和WebGPU TLDR 在Apache TVM深度学习编译器中引入了对WASM和WebGPU的支持.实验表明,在将模型部署到Web时,TVM的WebG ...
- TVM编译机器学习到 WASM 和 WebGPU
TVM编译机器学习到 WASM 和 WebGPU TLDR TVM 深度学习编译器对 WASM 和 WebGPU 的支持.实验表明,TVM 的 WebGPU 后端在将模型部署到 Web 时可以接近原生 ...
- 端到端TVM编译器(上)
端到端TVM编译器(上) 摘要 将机器学习引入到各种各样的硬件设备中.AI框架依赖于特定于供应商的算子库,针对窄范围的服务器级gpu进行优化.将工作负载部署到新平台,例如手机.嵌入式设备和加速器(例如 ...
- TVM设计与构架构建
TVM设计与构架构建 本文档适用于希望了解TVM体系结构和/或在项目上进行积极开发的开发人员.该页面的组织如下: 实例编译流程Example Compilation Flow描述TVM把一个模型的高级 ...
- TVM 架构设计
TVM 架构设计 本文面向希望了解TVM体系结构和/或积极参与项目开发的开发人员. 主要内容如下: 示例编译流程概述了TVM将模型的高级概念转换为可部署模块的步骤. 逻辑架构组件部分描述逻辑组件.针对 ...
随机推荐
- 在 Y 分钟内学会 Python
在 Y 分钟内学会 Python 这是翻译, 原文地址: Learn Python in Y Minutes 在 90 年代初, Python 由 Guido van Rossum 创造, 现在, 它 ...
- 12- winmerge讲解
WinMerge是一款运行于Windows系统下的免费开源的文件比较/合并的工具,使用它可以非常方便的比较多个文档内容设置是文件夹与文件夹之间的差异.适合程序员或者经常撰写文稿的朋友使用.
- Google Hacking的用法
目录 Google Hacking 基本搜索 高级搜索 Index of inurl Google Hacking Google Hacking 是利用谷歌搜索的强大,来在浩瀚的互联网中搜索到我们需要 ...
- PowerShell-4.API调用以及DLL调用
PowerShell可以直接调用API,So...这东西完全和cmd不是一回事了... 调用API的时候几乎和C#一样(注意堆栈平衡): 调用MessageBox: $iii = Add-Type - ...
- MySQL的Double Write并不难理解
目录 问题引入- 断电了 不一会 - 来电了 Double write工作流程 恢复的过程 配置参数 疑问 推荐阅读 问题引入- 断电了 今天为大家介绍一个新的名词:double write. 相信你 ...
- canvas绘制虚线图表
最近有读者加我微信咨询这个问题,如下图所示: 要实现的效果如下: 其实难度不大,但是考虑一些人员对于canvas不熟悉,还是简单的介绍下. 其实该图表,就是一个圆圈外面在套一个圆弧的效果, 主要的难点 ...
- [CSP-J2019 江西] 道路拆除 题解
发现大家都是将路径拆成三条链来做,这里提供一种暴力的乱搞方法. 思路 看到这一道题的第一想法就是跑最短路.可是仔细想想就发现,由于重合的路径只算一遍,所以导致两条最短路不一定是最优解. 接着,看到数据 ...
- Error starting userland proxy: /forwards/expose/port returned unexpected status: 500.
欢迎关注微信公众号 Error starting userland proxy: /forwards/expose/port returned unexpected status: 500. dock ...
- LinkedList作为栈和队列的使用
最近在LeekCode用java写一些算法时,经常遇到要使用栈和队列结构,使用栈的话,Stack已经不被推荐使用了,所以栈和队列我们通常都是用LinkedList这种双链表结构实现.Linkedlis ...
- stm32开发笔记(二):stm32系列使用V3.5固件库的帮助文件以及GPIO基本功能(一)
前言 stm32系列是最常用的单片机之一,不同的版本对应除了引脚.外设.频率.容量等'不同之外,其开发的方法是一样的. 本章讲解使用库函数使用GPIO引脚功能. 补充 本文章为多年前学习 ...