目录
X86Ubuntu的TVM
安装LLVM
下载tvm
配置config.cmake
编译源码
python安装
测试是否安装成功
可以在安装一些库,用于RPC Tracker和auto-tuning
交叉编译801 arm的TVM
交叉编译链
下载
配置config.cmake
编译源码
编译的时候可能会遇到错误
ONNX模型转换为TVM模型
创建pre.py,将onnx模型编译成tvm.so文件
测试TVM模型
修改demo程序
创建CMakeList.txt
运行demo
在801板子上创建并进入文件夹
设置环境变量
运行
参考:
这里推荐LLVM8.0
#安装
sudo apt-get install llvm-8 clang
#配置
export LLVM_HOME=/usr/lib/llvm-8
export PATH=$LLVM_HOME/bin:$PATH
#查看是否安装成功
llvm-config --version
clang --version
git clone --recursive https://github.com/apache/tvm tvm
备注:得有代理才能直接下载,没有代理的话,会造成第三方库不全的情况。
这样手动到https://github.com/apache/tvm的3rd文件下,下载需要下载的第三方库
cd tvm
mkdir build
cp cmake/config.cmake build
cd build
修改config.cmake,把需要的选项添加上
# 使用llvm编译
set(USE_LLVM "/usr/lib/llvm-8 --link-static")
set(HIDE_PRIVATE_SYMBOLS ON)
# 调试 IR
set(USE_RELAY_DEBUG ON)
# 使用onnx,需要你的python环境中已经安装有onnx
set(USE_TARGET_ONNX ON)
# 使用pytorch,需要你的python环境中已经安装有pytorch
set(USE_PT_TVMDSOOP ON)
# 关掉这个可以解决掉make时的某个warning
set(USE_LIBBACKTRACE OFF)
cmake ..
make -j8
在build目录下
cd ..
cd python
python3 setup.py install --user
最好挂上代理,不然可能会出错
import tvm
print(tvm.__version__)
pip3 install --user tornado psutil xgboost cloudpickle
交叉编译链推荐7.5.0,我的交叉编译链路径为
/home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf/bin/
git clone --recursive https://github.com/apache/tvm tvm_arm
cd tvm
mkdir build
cp cmake/config.cmake build
cd build
修改config.cmake,把需要的选项添加上,因为801板子上没有CUDA,所以不需要修改
##tvm编译运行时
cmake .. \
-DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_SYSTEM_VERSION=1 \
-DCMAKE_C_COMPILER=/home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc \
-DCMAKE_CXX_COMPILER=/home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ \
-DCMAKE_FIND_ROOT_PATH=/home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf \
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
-DMACHINE_NAME=arm-linux-gnueabihf
make -j8 runtime
备注:只需要编译运行时即可
arm-linux-gnueabihf-g++: error: unrecognized command line option ‘-fuse-ld=lld’; did you mean ‘-fuse-ld=bfd’?
make[3]: *** [CMakeFiles/tvm_runtime.dir/build.make:178: libtvm_runtime.so] Error 1
make[2]: *** [CMakeFiles/Makefile2:203: CMakeFiles/tvm_runtime.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:262: CMakeFiles/runtime.dir/rule] Error 2
make: *** [Makefile:248: runtime] Error 2
在build目录下修改
vim ./CMakeFiles/tvm_runtime.dir/link.txt
删除-fuse-ld=lld并保存,编译通过,得到libtvm_runtime.so
import numpy as np
from tvm import te
import onnx
import numpy as np
import tvm
import tvm.relay as relay
from tvm import rpc
from tvm.contrib import utils
x = np.zeros((1,3, 640, 640))
target = tvm.target.Target('llvm -mtriple=arm-linux-gnueabihf -mcpu=cortex-a7 -mfloat-abi=hard')
input_name = "images"
shape_dict = {input_name: x.shape}
#导入onnx模型
onnx_model = onnx.load("./model.onnx")
sym, params = relay.frontend.from_onnx(onnx_model, shape_dict)
# 这里利用TVM构建出优化后模型的信息
with relay.build_config(opt_level=3):
lib = relay.build_module.build(sym, target, params=params)
#这个relay.build_module.build与relay.build一样;
dtype = 'float32'
from tvm.contrib import graph_runtime
# 下面的函数导出我们需要的动态链接库,地址可自定义
print("Output model files")
libpath = "model.so"
from tvm.contrib import cc
lib.export_library(libpath,tvm.contrib.cc.create_shared, cc="/home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++")
特别注意target不要搞错了,选项有
-device=arm_cpu:指定目标设备为ARM CPU,这将使LLVM编译生成ARM架构的目标代码。
-mtriple=arm-linux-gnueabihf:指定目标设备的三元组(triple),即CPU架构、操作系统和ABI(应用程序二进制接口)。arm-linux-gnueabihf表示使用Linux操作系统和GNU工具链,采用硬件浮点运算。
-mattr=+neon:启用NEON指令集,NEON是ARM体系结构的向量处理单元,用于加速多媒体和信号处理等应用。
-mcpu=cortex-a7:指定目标CPU为Cortex-A7,Cortex-A7是ARM公司推出的一款低功耗应用处理器。
-mfloat-abi=hard:指定浮点运算的ABI为硬件实现,即使用浮点寄存器执行浮点运算,而不是通过函数调用实现浮点运算。
我之前就是添加了-mattr=+neon,导致运行的时候段错误,可以通过在板子上lscpu来查看板子支持的指令集,看是否支持neon。
这是我的
Architecture: armv7l
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
Vendor ID: ARM
Model: 5
Model name: Cortex-A7
Stepping: r0p5
CPU max MHz: 800.0000
CPU min MHz: 100.0000
BogoMIPS: 1600.00
Flags: half thumb fastmult vfp edsp vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
顺利的话得到model.so
进入到/home/chen/Downloads/tvm1/apps/howto_deploy/
注释掉// DeploySingleOp();
int main(void) {
// DeploySingleOp();
DeployGraphExecutor();
return 0;
}
修改DeployGraphExecutor函数将输入输出改成自己的
void DeployGraphExecutor() {
LOG(INFO) << "Running graph executor...";
// load in the library
DLDevice dev{kDLCPU, 0};
tvm::runtime::Module mod_factory = tvm::runtime::Module::LoadFromFile("./models.so");
// create the graph executor module
tvm::runtime::Module gmod = mod_factory.GetFunction("default")(dev);
tvm::runtime::PackedFunc set_input = gmod.GetFunction("set_input");
tvm::runtime::PackedFunc get_output = gmod.GetFunction("get_output");
tvm::runtime::PackedFunc run = gmod.GetFunction("run");
// Use the C++ API
tvm::runtime::NDArray images = tvm::runtime::NDArray::Empty({1,3,640, 640}, DLDataType{kDLFloat, 32, 1}, dev);
tvm::runtime::NDArray output0 = tvm::runtime::NDArray::Empty({1,6, 8400}, DLDataType{kDLFloat, 32, 1}, dev);
set_input("images", images);
LOG(INFO) << "先运行两次";
for(int i=0;i<2;i++){
run();
}
LOG(INFO) << "运行10次平均时间:";
struct timeval t0, t1;
int times = 10;
gettimeofday(&t0, 0);
printf("run the code\n");
for(int i=0;i
cmake_minimum_required(VERSION 3.2)
project(how2delploy C CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O2 -fPIC")
set(CMAKE_C_COMPILER /home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /home/chen/Downloads/toolchain/gcc-linaro-7.5.0-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ )
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O3 -Wall -g2 -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -fPIC")
set(TVM_ROOT /home/chen/Downloads/tvm1)
set(DMLC_CORE ${TVM_ROOT}/3rdparty/dmlc-core)
include_directories(${TVM_ROOT}/include)
include_directories(${DMLC_CORE}/include)
include_directories(${TVM_ROOT}/3rdparty/dlpack/include)
link_directories(${TVM_ROOT}/build/Release)
add_definitions(-DDMLC_USE_LOGGING_LIBRARY=)
add_executable(cpp_deploy_norm cpp_deploy.cc)
target_link_libraries(cpp_deploy_norm -Wl,--no-as-needed -lrt -ldl -pthread ${TVM_ROOT}/build/libtvm_runtime.so)
mkdir build & cd build
cmake ..
make -j8
得到cpp_deploy_norm
mkdir test & cd test
mkdir lib
将cpp_deploy_norm和model.so拷贝到test目录下
将libtvm_runtime.so拷贝到./test/lib目录下
目录结构
test-|
|-lib-|
|-libtvm_runtime.so
|-cpp_deploy_norm
|-model.so
export LD_LIBRARY_PATH=/home/test/lib
chmod 777 cpp_deploy_norm
./cpp_deploy_norm
[TVM] 编译与安装
TVM的安装过程