TVM Compiler中文教程:TVM编译ONNX模型并执行

本文是TVM Compiler的中文教程,详细介绍了如何加载预训练的ONNX模型,加载测试图像,通过Relay进行模型编译,并在TVM上执行,最后展示执行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编译ONNX模型

下面描述使用Relay如何部署ONNX模型:

#安装onnx,https://github.com/onnx/onnx
pip install onnx --user

首先导入所需要的python包:

import onnx 
import numpy as np
import tvm
import tvm.relay as relay
from tvm.contrib.download import download_testdata

加载预训练ONNX模型

model_url = ''.join(['https://gist.github.com/zhreshold/', 'bcda4716699ac97ea44f791c24310193/raw/','93672b029103648953c4e5ad3ac3aadf346a4cdc/','super_resolution_0.2.onnx'])
model_path = download_testdata(model_url, 'super_resolution.onnx', module='onnx')
#从硬盘加载supe_resolution.onnx
onnx_model = onnx.load(model_path)

加载一张测试图像

from PIL import Image
img_url = 'https://github.com/dmlc/mxnet.js/blob/master/data/cat.png?raw=true'
img_path = download_testdata(img_url, 'cat.png', module='data')
img = Image.open(img_path).resize((224,224))
img_ycbcr = img.convert("YCbCr")
img_y, img_cb, img_cr = img_ycbcr.split()
x = np.array(img_y)[np.newaxis, np.newaxis, :, :]

使用relay编译模型

target = 'llvm'
input_name = '1'
shape_dict = {input_name: x.shape}
sym, params = relay.frontend.from_onnx(onnx_model, shape_dict)
with relay.build_config(opt_level = 1):
    intrp = relay.build_module.create_executor('graph',sym, tvm.cpu(0), target)

在TVM上执行

dtype = 'float32'
tvm_output = intrp.evaluate(sym)(tvm.nd.array(x.astype(dtype)),**params).asnumpy()

显示结果

from matplotlib import pyplot as plt
out_y = Image.fromarray(np.uint8((tvm_output[0,0]).clip(0, 255)),model='L')
out_cb = img_cb.resize(out_y.size, Image.BICUBIC)
out_cr = img_cr.resize(out_y.size, Image.BICUBIC)
result = Image.merge('YCbCr', [out_y, out_cb, out_cr]).convert('RGB')
canvas = np.full((672,672*2,3),255)
canvas[0:224, 0:224, :] = np.asarray(img)
canvas[:, 672:, :] = np.asarray(result)
plt.imshow(canvas.astype(np.uint8))
plt.show()
<think>我们正在处理一个关于在Ubuntu18.04上从源码编译TVM0.9以支持x86和ARMv7架构,部署QLinear模型到ARMv7设备的问题。根据提供的引用,我们可以整合以下步骤:1.安装必要的依赖(参考引用[2]和引用[3]):-构建工具和Python相关工具(引用[2])-交叉编译工具链(引用[3])2.下载编译LLVM(参考引用[1]):-注意选择与TVM0.9兼容的LLVM版本(引用[1]提到tvm0.7.dev1+LLVM10.0.0可用,但我们需要为TVM0.9选择合适版本,一般TVM文档会推荐版本,比如LLVM14或15,但需要验证) 3.编译TVM源码,配置支持x86和ARMv7。4.编译QLinear模型部署到ARMv7设备。 由于用户的问题涉及多个步骤,我们将分步骤详细说明。 ###步骤1:安装系统依赖根据引用[2],我们需要安装一些基础构建工具:```bashsudoapt updatesudoapt install-ypython3python3-devpython3-setuptoolsgcclibtinfo-devzlib1g-dev build-essentialcmakelibedit-dev libxml2-dev``` ###步骤2:安装ARM交叉编译工具链根据引用[3],我们需要安装ARMv7的交叉编译工具链: ```bashsudo aptinstall -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf```设置环境变量(在编译TVM模型时可能需要):```bashexportCC=arm-linux-gnueabihf-gccexport CXX=arm-linux-gnueabihf-g++ exportLD=arm-linux-gnueabihf-ldexport RANLIB=arm-linux-gnueabihf-ranlibexport AR=arm-linux-gnueabihf-ar``` ###步骤3:下载编译LLVM根据引用[1],我们需要下载LLVM。由于TVM0.9可能需要较新的LLVM版本,建议参考TVM官方文档。这里我们选择LLVM14.0.0(因为TVM0.9可能支持,但请根据实际情况调整):```bashwgethttps://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/llvm-14.0.0.src.tar.xztar -xf llvm-14.0.0.src.tar.xzcd llvm-14.0.0.srcmkdirbuildcd buildcmake -DCMAKE_BUILD_TYPE=Release-DLLVM_ENABLE_PROJECTS="clang"-DLLVM_TARGETS_TO_BUILD="X86;ARM"-DLLVM_ENABLE_TERMINFO=OFF-DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_INSTALL_PREFIX=/opt/llvm14.. make-j$(nproc) sudomake install```将LLVM添加到环境变量:```bashexportPATH=/opt/llvm14/bin:$PATHexportLD_LIBRARY_PATH=/opt/llvm14/lib:$LD_LIBRARY_PATH```###步骤4:下载TVM0.9源码```bashgit clone--recursive https://github.com/apache/tvm.gitcdtvmgitcheckout v0.9.0``` ###步骤5:配置TVM创建构建目录复制配置文件:```bashmkdirbuildcp cmake/config.cmakebuild``` 编辑`build/config.cmake`: -启用LLVM支持:`set(USE_LLVM /opt/llvm14/bin/llvm-config)` -启用ARM编译:`set(USE_LLVMON)`已经包含,但需要确保LLVM支持ARM目标(我们在编译LLVM时已经包括ARM) -如果需要其他后端(如OpenCL,Vulkan等)根据设备支持开启###步骤6:编译TVM```bashcdbuildcmake.. make-j$(nproc)``` ###步骤7:安装TVM的Python包设置环境变量,使得Python可以找到TVM:```bashexportTVM_HOME=/path/to/tvmexport PYTHONPATH=$TVM_HOME/python:${PYTHONPATH}``` ###步骤8:编译QLinear模型QLinear模型可能是量化模型TVM支持ONNX格式的模型。假设我们有一个ONNX格式的QLinear模型,我们可以使用TVM编译它。首先安装ONNX:```bashpip3install onnx```然后,使用TVM编译模型(编写Python脚本): -为x86编译(在主机上测试) -为ARMv7编译(部署到设备) ####为x86编译模型(示例):```pythonimporttvmfromtvmimport relayimportonnx#加载ONNX模型onnx_model =onnx.load("qlinear_model.onnx")#将ONNX模型转换为RelayIRtarget ="llvm -mcpu=skylake"#根据你的CPU调整input_name ="input" shape_dict ={input_name:(1,3,224,224)}mod,params =relay.frontend.from_onnx(onnx_model,shape_dict) #编译模型with tvm.transform.PassContext(opt_level=3):lib =relay.build(mod,target=target,params=params)#保存编译后的模型lib.export_library("qlinear_model_x86.so")``` ####为ARMv7编译模型:```pythontarget= "llvm-device=arm_cpu-mtriple=arm-linux-gnueabihf-mattr=+neon"withtvm.transform.PassContext(opt_level=3):lib= relay.build(mod, target=target, params=params) #保存编译后的模型lib.export_library("qlinear_model_armv7.so") ```###步骤9:部署到ARMv7设备将生成的`qlinear_model_armv7.so`和TVM的运行时库(在TVM编译时生成的`libtvm_runtime.so`)复制到ARMv7设备上。在设备上,我们可以使用TVM的Python接口或C++接口加载模型运行。在ARM设备上安装TVM的Python包(如果使用Python): -在ARM设备上从源码编译TVM运行时(只需要runtime),或者使用交叉编译生成runtime。但最简单的方法是在ARM设备上安装tvm-runtime包(如果有预编译包)或者从源码编译(注意设备资源可能有限)。编译TVM运行时(在设备上): ```bashgit clone--recursive https://github.com/apache/tvm.gitcdtvmgitcheckout v0.9.0mkdir buildcpcmake/config.cmake build#编辑config.cmake,只设置USE_LLVMOFF(如果没有LLVM),其他根据设备能力设置cdbuildcmake.. makeruntime -j$(nproc)``` 然后在Python脚本中加载模型:```pythonimporttvmfrom tvm importrelayimport numpyas np#加载模型lib =tvm.runtime.load_module("qlinear_model_armv7.so")dev =tvm.cpu(0) module= tvm.contrib.graph_executor.GraphModule(lib["default"](dev))#准备输入数据input_data= np.random.uniform(size=(1,3,224,224)).astype("float32")module.set_input("input",input_data) #运行module.run()output =module.get_output(0)``` ###注意事项1.交叉编译TVM运行时:上述步骤中,我们是在主机上交叉编译模型,然后在设备上运行。设备上需要TVM运行时库(libtvm_runtime.so)和模型共享库。2.模型格式:确保QLinear模型TVM支持的格式(如ONNX)。如果模型是其他格式(如TensorFlow Lite),需要使用相应的前端转换。 3.设备依赖:部署到ARM设备时,注意设备的浮点支持(如是否支持NEON)和ABI(如gnueabihf)。###相关问题1.如何验证TVM是否成功编译支持ARMv7目标? 2.在交叉编译TVM模型时,如何处理模型中的特定算子(如量化算子)? 3.部署到ARMv7设备时,如何优化TVM模型的性能?</think>### 在Ubuntu 18.04上编译TVM 0.9支持双架构部署QLinear模型 #### 1. 安装系统依赖 ```bash sudo apt update sudo apt install -y \ python3 python3-dev python3-pip python3-setuptools git ninja-build \ gcc g++ make cmake libtinfo-dev zlib1g-dev libedit-dev libxml2-dev \ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf # ARM交叉编译工具链[^3] ``` #### 2. 安装LLVM(建议版本14+) ```bash wget https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.0/clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz tar -xf clang+llvm-*.tar.xz sudo mv clang+llvm-14.0.0-x86_64-linux-gnu-ubuntu-18.04 /opt/llvm14 echo 'export PATH=/opt/llvm14/bin:$PATH' >> ~/.bashrc source ~/.bashrc ``` #### 3. 编译TVM 0.9源码 ```bash git clone --recursive -b v0.9 https://github.com/apache/tvm.git cd tvm mkdir build && cd build ``` 配置`config.cmake`: ```cmake # 启用LLVM支持 set(USE_LLVM ON) set(USE_LLVM "/opt/llvm14/bin/llvm-config") # 启用ARM交叉编译 set(USE_ARM_COMPUTE_LIB ON) set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc) set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++) # 启用量化支持(QLinear必需) set(USE_RELAY_DEBUG ON) set(USE_GRAPH_EXECUTOR ON) ``` 编译TVM: ```bash cmake -DCMAKE_BUILD_TYPE=Release .. make -j$(nproc) ``` #### 4. 配置Python环境 ```bash pip install numpy decorator attrs echo 'export TVM_HOME=$(pwd)' >> ~/.bashrc echo 'export PYTHONPATH=$TVM_HOME/python:${PYTHONPATH}' >> ~/.bashrc source ~/.bashrc ``` #### 5. 编译QLinear模型 创建编译脚本`compile_model.py`: ```python import tvm from tvm import relay import onnx # 需pip install onnx # 加载ONNX格式的QLinear模型 model = onnx.load("qlinear_model.onnx") # 转换为Relay IR mod, params = relay.frontend.from_onnx(model) # 交叉编译配置 arm_target = tvm.target.arm_cpu("raspberry-pi/armv7l") # 根据设备调整 # 编译双架构 with tvm.transform.PassContext(opt_level=3): # 编译ARM版本 arm_lib = relay.build(mod, target=arm_target, params=params) arm_lib.export_library("qlinear_arm.so") # 编译x86版本(测试用) x86_lib = relay.build(mod, target="llvm", params=params) x86_lib.export_library("qlinear_x86.so") ``` #### 6. 部署到ARMv7设备 将生成的文件复制到ARM设备: ```bash scp qlinear_arm.so user@arm-device:/path/ scp $TVM_HOME/build/libtvm_runtime.so user@arm-device:/path/ ``` 在ARM设备上运行: ```python import tvm from tvm import runtime # 加载模型 dev = tvm.cpu(0) lib = runtime.load_module("qlinear_arm.so") module = runtime.GraphModule(lib["default"](dev)) # 执行推理 module.set_input("input_name", input_data) module.run() output = module.get_output(0) ``` ### 关键注意事项 1. **量化支持**:确保TVM编译时开启`USE_RELAY_DEBUG`,QLinear模型需要量化算子支持 2. **ARM ABI兼容**:使用`arm-linux-gnueabihf`工具链保证硬件浮点支持 3. **设备特定优化**:在`arm_target`中指定具体设备型号(如`raspberry-pi/bcm2837`) 4. **依赖库**:部署时需同步`libtvm_runtime.so`和模型SO文件 ### 相关问题 1. 如何验证TVM是否正确启用了ARM交叉编译支持? 2. 当QLinear模型包含自定义算子时,TVM如何处理? 3. 在ARMv7低内存设备上部署TVM模型有哪些优化技巧? 4. 如何利用TVM的AutoTVM功能优化QLinear模型在ARM架构的性能? 5. TVM部署时如何实现模型的热更新而不重启应用?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值