设为首页|收藏本站|
开启左侧

[问答] 【4】TVM-1:TVM框架量化上手第一个代码-附python程序

[复制链接]
42838 0
徐狗狗 发表于 2022-9-7 01:03:59 | 只看该作者 打印 上一主题 下一主题
 
上一个文档(传送门如下),我们讲了TVM在wins下安装教程,
安装完以后用一个preprocess.py前处理程序验证已安装成功TVM,接下来我们就上手一个量化模型例子吧!
不过,在庖丁解牛之前,我们还是有必要了解下整个TVM的流程。先打好基础,再上手代码会更好一些。
1. TVM整体流程介绍


【4】TVM-1:TVM框架量化上手第一个代码-附python程序 第1张图片

TVM框架处理框图

(1)模型导入

从Tensorflow/pytorch或ONNX等框架导入模型
import层是TVM从其他框架中导入模型的地方
注:TVM为每个前端提供的支持水平不尽相同,若导入有问题,可尝试将模型转换为ONNX再导入;
(2)转换到Relay

Relay是TVM的高级模型语言,导入到TVM的模型是用Relay表示的。Relay是一种函数式语言(function language)和神经网络的中间表示法(intermediate representation,IR),它支持以下内容:
传统的数据流图式表示法
Functional-style scoping 和 let-binding 使其成为一种功能齐全的可微分语言
能够允许用户混合两种编程风格
Relay应用图级(graph-level)优化passes来优化模型
(3)TE表示:Lower to Tensor Expression (TE) representation

lower是指较高层表示转换成较低层表示。在high-level经过优化后,Relay 运行 FuseOps,将模型分割成许多小的子图,并将子图 lower 到 TE 表示。TE 即Tensor Expression,张量表达,是描述张量计算的专属性语言。TE 还提供了一些schedule 原语来指定低级的循环优化,例如平铺(tiling)、矢量化(vectorization)、并行化(parallelization)、unrolling 和 fusion。
为了帮助将 Relay 表示转换为 TE 表示的过程,TVM 包含张量算子清单(Tensor Operator Inventory, TOPI),它有预先定义的常见张量算子的模板(如 conv2d、transpose)。
(4)Search for the best schedule using the auto-tuning module AutoTVM or AutoScheduler.
schedule 指定在 TE 中定义了算子或子图的低级循环优化。auto-tuning 模块搜索最佳 schedule 并将其与 cost 模型和设备上的测量结果进行比较。
在 TVM 中,有两个 auto-tuning 模块:



  • AutoTVM: 基于模板的 auto-tuning 模块。它运行搜索算法为用户定义的模板中的可调节旋钮找到最佳值。对于常见的运算符,其模板已经在 TOPI 中提供。
  • AutoScheduler (别名 Ansor) :无模板的auto-tuning 模块。它不需要预先定义的 schedule 模板。相反,它通过分析计算的定义自动生成搜索空间。然后,它在生成的搜索空间中搜索最佳 schedule。
(5)Choose the optimal configurations for model compilation.
tuning 后,auto-tuning 模块会生成 JSON 格式的 auto-tuning 记录。这一步为每个子图挑选出最佳的 schedule。


(6)Lower to Tensor Intermediate Representation (TIR),TVM's low-level intermediate representation
TIR 是张量级的中间表示(Tensor Intermediate Representation),TVM 的低层次中间表示。


在根据 tuning 步骤选择最佳配置后,每个 TE 子图被降低到 TIR,并通过低级别的优化 passes 进行优化。
接下来,优化后的 TIR 被 lower 到硬件平台的目标编译器中。这是最后的代码生成阶段,产生可以部署到生产中的优化模型。
TVM 支持几种不同的编译器后端,包括:

  • LVM:它可以针对任意的微处理器架构,包括 标准 x86 和 ARM 处理器,AMDGPU 和 NVPTX 代码生成,以及 LLVM 支持的任何其他平台。
  • 专门的编译器,如 NVCC,NVIDIA 的编译器。
  • 嵌入式和专用目标,通过 TVM 的 Bring Your Own Codegen(BYOC)框架实现。
(7)Compile down to machine code.
在这个过程结束时,特定的编译器生成的代码可以 lower 为机器码。


TVM 可以将模型编译成可链接的对象模块,然后可以用轻量级的 TVM 运行时来运行,该运行时提供 C 语言的 API 来动态加载模型,以及其他语言的入口,如 Python 和 Rust。TVM 还可以建立捆绑式部署,其中运行时与模型结合在一个包中。
2. 实例上手

2-1:前序工作: 环境:cp37, cpu,

    1)pip install onnx onnxoptimizer
    2)pip install torch
    3)pip install torchvision
    4)安装LLSM,链接在上一文的文末,打开链接选择下述下载安装:

【4】TVM-1:TVM框架量化上手第一个代码-附python程序 第2张图片
2-2:代码展示

# -*- coding: utf-8 -*-
"""
Created on Wed Aug 31 15:39:54 2022

@author: Albert, emAIl: 196659042@qq.com
"""
#导入库
import tvm
from tvm import relay

import numpy as np

from tvm.contrib.download import download_testdata

# PyTorch imports
import torch
import torchvision

#加载pytorch预训练模型
model_name = "resnet101"  # 可resnet18, resnet101
model = getattr(torchvision.models, model_name)(pretrained=True)
model = model.eval()

# We grab the TorchScripted model via tracing
input_shape = [1, 3, 224, 224]
input_data = torch.randn(input_shape)
scripted_model = torch.jit.trace(model, input_data).eval()

#加载一张测试图片 - 经典的图片
from PIL import Image

img_url = "https://s3.amazonaws.com/model-server/inputs/kitten.jpg"
img_path = download_testdata(img_url, "imagenet_cat.png", module="data")
img = Image.open(img_path).resize((224, 224))
img.show()
# Preprocess the image and convert to tensor
from torchvision import transforms

my_preprocess = transforms.Compose(
    [
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ]
)
img = my_preprocess(img)
img = np.expand_dims(img, 0)

#Import the graph to Relay
# 将Pytorch 图转换为Relay图,Input name是随意的
input_name = "input0"
shape_list = [(input_name, img.shape)]
mod, params = relay.frontend.from_pytorch(scripted_model, shape_list)

#Relay Build
# 使用给定的输入将graph图编译成llvm目标

target = tvm.target.Target("llvm", host="llvm")
dev = tvm.cpu(0)
with tvm.transform.PassContext(opt_level=3):
        lib = relay.build(mod, target=target, params=params)


##% TVM上执行可移植图(Execute the portable graph on TVM)
# 现在,尝试在目标上部署已编译的模型
from tvm.contrib import graph_executor

dtype = "float32"
m = graph_executor.GraphModule(lib["default"](dev))
# Set inputs
m.set_input(input_name, tvm.nd.array(img.astype(dtype)))
# Execute
m.run()
# Get outputs
tvm_output = m.get_output(0)

#%% 输出后处理,将TVM输出结果转化为更易读的结果
#其中的imagenet_synsets.txt和imagenet_classes.txt两个文件,url链接出错的话可自行下载:
# https://github.com/Cadene/pretrained-models.pytorch/blob/master/data/ 下

synset_url = "".join(
    [
        "https://raw.githubusercontent.com/Cadene/",
        "pretrained-models.pytorch/master/data/",
        "imagenet_synsets.txt",
    ]
)
synset_name = "imagenet_synsets.txt"
synset_path = download_testdata(synset_url, synset_name, module="data")
with open(synset_path) as f:
    synsets = f.readlines()

synsets = [x.strip() for x in synsets]
splits = [line.split(" ") for line in synsets]
key_to_classname = {spl[0]: " ".join(spl[1:]) for spl in splits}

class_url = "".join(
    [
        "https://raw.githubusercontent.com/Cadene/",
        "pretrained-models.pytorch/master/data/",
        "imagenet_classes.txt",
    ]
)
class_name = "imagenet_classes.txt"
class_path = download_testdata(class_url, class_name, module="data")
with open(class_path) as f:
    class_id_to_key = f.readlines()

class_id_to_key = [x.strip() for x in class_id_to_key]

# Get top-1 result for TVM
top1_tvm = np.argmax(tvm_output.numpy()[0])
tvm_class_key = class_id_to_key[top1_tvm]

# Convert input to PyTorch variable and get PyTorch result for comparison
with torch.no_grad():
    torch_img = torch.from_numpy(img)
    output = model(torch_img)

    # Get top-1 result for PyTorch
    top1_torch = np.argmax(output.numpy())
    torch_class_key = class_id_to_key[top1_torch]

print("Relay top-1 id: {}, class name: {}".format(top1_tvm, key_to_classname[tvm_class_key]))
print("Torch top-1 id: {}, class name: {}".format(top1_torch, key_to_classname[torch_class_key]))
输出结果为:

【4】TVM-1:TVM框架量化上手第一个代码-附python程序 第3张图片

输出结果

当然,imshow语句会显示出小猫咪图片,嘿嘿

【4】TVM-1:TVM框架量化上手第一个代码-附python程序 第4张图片

imagenet_cat.png

【注】上述代码过程是对比了torch模型预测结果和将Resnet模型用TVM runtime编译后的模型预测输出,还不涉及到TVM的量化处理过程;关于TVM的量化处理后续文章会有的~
代码见:https://github.com/Learneruestc/TVM-all/tree/main/TVM1
先这样吧,有问题同学留言交流,后续再回头补充完善!
3. 后续工作

3-1:将TVM过程更细拆分出来,更好理解整个过程;

参考链接:
1)博客:从一个例子看tvm执行流程 - 牛犁heart - 博客园
2)官网:Compiling and Optimizing a Model with the Python Interface (AutoTVM)
姊妹篇传送:


上一篇:女的51岁交了8年的社保可以领失业金吗?
下一篇:初三了还有机会吗?
@



1.西兔生活网 CTLIVES 内容全部来自网络;
2.版权归原网站或原作者所有;
3.内容与本站立场无关;
4.若涉及侵权或有疑义,请点击“举报”按钮,其他联系方式或无法及时处理。
 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

排行榜
活跃网友
返回顶部快速回复上一主题下一主题返回列表APP下载手机访问
Copyright © 2016-2028 CTLIVES.COM All Rights Reserved.  西兔生活网  小黑屋| GMT+8, 2024-5-13 21:05