TVM部署预定义模型
TVM部署预定义模型
本文通过深度学习框架量化的模型加载到TVM中。预量化的模型导入是在TVM中提供的量化支持之一。
本文演示如何加载和运行由PyTorch,MXNet和TFLite量化的模型。加载后,可以在任何TVM支持的硬件上运行已编译的量化模型。
首先,必要输入
from PIL import Image
import numpy as np
import torch
from torchvision.models.quantization import mobilenet as qmobilenet
import tvm
from tvm import relay
from tvm.contrib.download import download_testdata
帮助程序功能来运行演示
def get_transform():
import torchvision.transforms as transforms
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
return transforms.Compose(
[
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
normalize,
]
)
def get_real_image(im_height, im_width):
img_url = "https://github.com/dmlc/mxnet.js/blob/main/data/cat.png?raw=true"
img_path = download_testdata(img_url, "cat.png", module="data")
return Image.open(img_path).resize((im_height, im_width))
def get_imagenet_input():
im = get_real_image(224, 224)
preprocess = get_transform()
pt_tensor = preprocess(im)
return np.expand_dims(pt_tensor.numpy(), 0)
def get_synset():
synset_url = "".join(
[
"https://gist.githubusercontent.com/zhreshold/",
"4d0b62f3d01426887599d4f7ede23ee5/raw/",
"596b27d23537e5a1b5751d2b0481ef172f58b539/",
"imagenet1000_clsid_to_human.txt",
]
)
synset_name = "imagenet1000_clsid_to_human.txt"
synset_path = download_testdata(synset_url, synset_name, module="data")
with open(synset_path) as f:
return eval(f.read())
def run_tvm_model(mod, params, input_name, inp, target="llvm"):
with tvm.transform.PassContext(opt_level=3):
lib = relay.build(mod, target=target, params=params)
runtime = tvm.contrib.graph_runtime.GraphModule(lib["default"](tvm.context(target, 0)))
runtime.set_input(input_name, inp)
runtime.run()
return runtime.get_output(0).asnumpy(), runtime
从标签到类名的映射,以验证以下模型的输出是否合理
synset = get_synset()
输出:
File /workspace/.tvm_test_data/data/imagenet1000_clsid_to_human.txt exists, skip.
每个人最喜欢的猫形象进行演示
inp = get_imagenet_input()
输出:
File /workspace/.tvm_test_data/data/cat.png exists, skip.
部署量化的PyTorch模型
首先,演示如何使用PyTorch前端加载由PyTorch量化的深度学习模型。
参考下面的PyTorch静态量化教程,以了解其量化工作流程。 https://pytorch.org/tutorials/advanced/static_quantization_tutorial.html
使用此功能来量化PyTorch模型。此函数采用浮点模型并将其转换为uint8。该模型是按通道量化的。
def quantize_model(model, inp):
model.fuse_model()
model.qconfig = torch.quantization.get_default_qconfig("fbgemm")
torch.quantization.prepare(model, inplace=True)
# Dummy calibration
model(inp)
torch.quantization.convert(model, inplace=True)
来自Torchvision的负载量化就绪,预训练的Mobilenet v2模型
选择mobilenet v2,该模型是通过量化训练的。其它型号需要完整的训练后校准。
qmodel = qmobilenet.mobilenet_v2(pretrained=True).eval()
量化,跟踪和运行PyTorch Mobilenet v2模型
pt_inp = torch.from_numpy(inp)
quantize_model(qmodel, pt_inp)
script_module = torch.jit.trace(qmodel, pt_inp).eval()
with torch.no_grad():
pt_result = script_module(pt_inp).numpy()
输出:
/usr/local/lib/python3.6/dist-packages/torch/quantization/observer.py:121: UserWarning: Please use quant_min and quant_max to specify the range for observers. reduce_range will be deprecated in a future release of PyTorch.
reduce_range will be deprecated in a future release of PyTorch."
/usr/local/lib/python3.6/dist-packages/torch/quantization/observer.py:990: UserWarning: must run observer before calling calculate_qparams. Returning default scale and zero point
Returning default scale and zero point "
使用PyTorch前端将量化的Mobilenet v2转换为Relay-QNN
PyTorch前端,将量化的PyTorch模型转换为充实了量化算子的等效Relay 模块。称这种表示为Relay QNN方言。
可以打印前端的输出,以查看量化模型的表示方式。
会看到特定于量化的算子,例如qnn.quantize,qnn.dequantize,qnn.requantize和qnn.conv2d等。
input_name = "input" # the input name can be be arbitrary for PyTorch frontend.
input_shapes = [(input_name, (1, 3, 224, 224))]
mod, params = relay.frontend.from_pytorch(script_module, input_shapes)
# print(mod) # comment in to see the QNN IR dump
编译并运行Relay 模块
一旦获得量化的Relay 模块,其余的工作流程与运行浮点模型相同。
在Under the hood下,量化专用算子在编译之前被降低为一系列标准Relay 算子。
tvm_result, rt_mod = run_tvm_model(mod, params, input_name, inp, target="llvm")
比较输出标签
应该看到打印出相同的标签。
pt_top3_labels = np.argsort(pt_result[0])[::-1][:3]
tvm_top3_labels = np.argsort(tvm_result[0])[::-1][:3]
print("PyTorch top3 labels:", [synset[label] for label in pt_top3_labels])
print("TVM top3 labels:", [synset[label] for label in tvm_top3_labels])
输出:
PyTorch top3 labels: ['tiger cat', 'Egyptian cat', 'lynx, catamount']
TVM top3 labels: ['tiger cat', 'Egyptian cat', 'tabby, tabby cat']
由于数值上的差异,通常预计原始浮点输出不会相同。打印来自mobilenet v2的1000个输出中有多少个浮点输出值相同。
print("%d in 1000 raw floating outputs identical." % np.sum(tvm_result[0] == pt_result[0]))
输出:
132 in 1000 raw floating outputs identical.
衡量性能
给出一个示例,说明如何测量TVM编译模型的性能。
n_repeat = 100 # should be bigger to make the measurement more accurate
ctx = tvm.cpu(0)
ftimer = rt_mod.module.time_evaluator("run", ctx, number=1, repeat=n_repeat)
prof_res = np.array(ftimer().results) * 1e3
print("Elapsed average ms:", np.mean(prof_res))
输出:
Elapsed average ms: 20.436994119999998
笔记
推荐此方法的原因如下:
- 测量是在C ++中完成的,因此没有Python开销
- 包括warm up runs
- 可以使用相同的方法在远程设备(Android等)上进行配置文件。
笔记
除非硬件对快速8位指令有特殊支持,否则量化模型不会比FP32模型快。如果没有快速的8位指令,即使模型本身是8位,TVM也会以16位进行量化卷积。
对于x86,在具有AVX512指令集的CPU上可以实现最佳性能。在这种情况下,TVM将最快可用的8位指令用于给定目标。这包括对VNNI 8位点产品指令(CascadeLake或更高版本)的支持。
此外,以下有关CPU性能的一般技巧同样适用:
- 将环境变量TVM_NUM_THREADS设置为物理核心数number of physical cores
- 选择最适合硬件的目标,例如“ llvm -mcpu = skylake-avx512”或“ llvm -mcpu = cascadelake”(将有更多带有AVX512的CPU)
TVM部署预定义模型的更多相关文章
- (三)使用预定义模型QDirModel的例子
使用预定义模型QDirModel的例子 Main.cpp #include <QApplication> #include "directoryviewer.h" in ...
- (二)使用预定义模型 QStringListModel例子
使用预定义模型 QStringListModel例子 源代码如下 Main.cpp #include <QApplication> #include "teamleadersdi ...
- VS2013 预定义的宏
Visual Studio 2013 预定义的宏 https://msdn.microsoft.com/zh-cn/library/b0084kay(v=vs.120).aspx 列出预定义的 ANS ...
- C#中一些默认的预定义属性
C#中一些默认的预定义属性,见下表: 预定义的属性 有效目标 说明 AttributeUsage Class 指定另一个属性类的有效使用方式 CLSCompliant 全部 指出程序元素是否与CLS兼 ...
- TVM将深度学习模型编译为WebGL
使用TVM将深度学习模型编译为WebGL TVM带有全新的OpenGL / WebGL后端! OpenGL / WebGL后端 TVM已经瞄准了涵盖各种平台的大量后端:CPU,GPU,移动设备等.这次 ...
- 使用Relay部署编译ONNX模型
使用Relay部署编译ONNX模型 本文介绍如何使用Relay部署ONNX模型的入门. 首先,必须安装ONNX软件包. 一个快速的解决方案是安装protobuf编译器,然后 pip install o ...
- TVM部署和集成Deploy and Integration
TVM部署和集成Deploy and Integration 本文包含如何将TVM部署到各种平台以及如何将其与项目集成. 与传统的深度学习框架不同.TVM堆栈分为两个主要组件: TVM编译器,完成所有 ...
- WebService -- Java 实现之 CXF ( 添加系统预定义的拦截器)
1. 概述 CXF允许我们在webservice的in/out位置添加拦截器.拦截器有两大分类,一类是系统预定义的:另一类是自定义拦截器. 2. 在server端添加拦截器. JaxWsServerF ...
- PHP预定义接口之 ArrayAccess
最近这段时间回家过年了,博客也没有更新,感觉少学习了好多东西,也错失了好多的学习机会,就像大家在春节抢红包时常说的一句话:一不留神错过了好几亿.废话少说,这篇博客给大家说说关于PHP预定义接口中常用到 ...
随机推荐
- 关于Oracle 数据库使用dba_tables或者all_tables或者user_tables统计数据时,与直接查询表统计时数据不一致的记录
1. 今天写代码发现这个问题,这里记录一下, 不一致的原因是因为 dba_tables .all_tables.user_tables 不是实时的反应表的数据的,所以需要在查询统计之前对表进行手动分 ...
- hdu4411 经典费用里建图
题意: 给以一个无向图,0 - n,警察在0,他们有k个警队,要派一些警队去1--n个城市抓小偷, 问所有吧所有小偷全抓到然后在返回0的最小路径和是多少,当地i个城市被攻击的时候他会通知i ...
- Iptables防火墙实验
先说明一下环境,这里有四台主机,中间的Centos充当防火墙.右上角的win XP和右下角的Rhel7充当服务器,最左边的win7充当主机.四者之间的网卡都已经配置好.而且我们已经在Centos6.5 ...
- Qt链接MySQL发布后Drive not loadedDrive not loaded怎么办
缺少动态链接库!把MySQL文件夹下面带dll.lib的全复制进去就行了
- 【JavaScript】Leetcode每日一题-移除元素
[JavaScript]Leetcode每日一题-移除元素 [题目描述] 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用 ...
- .NET 反射(Reflection)
这节讲一下.NET 中的一个技术:反射(Reflection). 反射是一种很重要的技术,它可以在程序运行时,动态的获取类的实例,并调用实例中的任何方法.它就像一面镜子,映射出一个类的所有细节. ...
- [MySQL数据库之表的详细操作:存储引擎、表介绍、表字段之数据类型]
[MySQL数据库之表的详细操作:存储引擎.表介绍.表字段之数据类型] 表的详细操作 存储引擎 mysql中建立的库======>文件夹 库中建立的表======>文件 用来存储数据的文件 ...
- Django(27)类视图
类视图 在写视图的时候,Django除了使用函数作为视图,也可以使用类作为视图.使用类视图可以使用类的一些特性,比如继承等. View django.views.generic.base.View是主 ...
- 记一次 .NET 某外贸Web站 内存泄漏分析
一:背景 1. 讲故事 上周四有位朋友加wx咨询他的程序内存存在一定程度的泄漏,并且无法被GC回收,最终机器内存耗尽,很尴尬. 沟通下来,这位朋友能力还是很不错的,也已经做了初步的dump分析,发现了 ...
- 【转载】基于Linux命令行KVM虚拟机的安装配置与基本使用
基于Linux命令行KVM虚拟机的安装配置与基本使用 https://alex0227.github.io/2018/06/06/%E5%9F%BA%E4%BA%8ELinux%E5%91%BD%E4 ...