【TVM 教程】microTVM PyTorch 教程

部署运行你感兴趣的模型镜像

Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 →https://tvm.hyper.ai/

作者:Mehrdad Hessar

该教程展示了如何使用 PyTorch 模型进行 microTVM 主机驱动的 AOT 编译。此教程可以在使用 C 运行时(CRT)的 x86 CPU 上执行。

注意: 此教程仅在使用 CRT 的 x86 CPU 上运行,不支持在 Zephyr 上运行,因为该模型不适用于我们当前支持的 Zephyr 单板。

安装 microTVM Python 依赖项

TVM 不包含用于 Python 串行通信包,因此在使用 microTVM 之前我们必须先安装一个。我们还需要TFLite来加载模型。

pip install pyserial==3.5 tflite==2.1
import pathlib
import torch
import torchvision
from torchvision import transforms
import numpy as np
from PIL import Image

import tvm
from tvm import relay
from tvm.contrib.download import download_testdata
from tvm.relay.backend import Executor
import tvm.micro.testing

加载预训练 PyTorch 模型

首先,从 torchvision 中加载预训练的 MobileNetV2 模型。然后,下载一张猫的图像并进行预处理,以便用作模型的输入。

model = torchvision.models.quantization.mobilenet_v2(weights="DEFAULT", quantize=True)
model = model.eval()

input_shape = [1, 3, 224, 224]
input_data = torch.randn(input_shape)
scripted_model = torch.jit.trace(model, input_data).eval()

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")
img = Image.open(img_path).resize((224, 224))

# 预处理图片并转换为张量
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)

input_name = "input0"
shape_list = [(input_name, input_shape)]
relay_mod, params = relay.frontend.from_pytorch(scripted_model, shape_list)

输出:

/venv/apache-tvm-py3.8/lib/python3.8/site-packages/torch/ao/quantization/utils.py:310: UserWarning: must run observer before calling calculate_qparams. Returning default values.
  warnings.warn(
Downloading: "https://download.pytorch.org/models/quantized/mobilenet_v2_qnnpack_37f702c5.pth" to /workspace/.cache/torch/hub/checkpoints/mobilenet_v2_qnnpack_37f702c5.pth

  0%|          | 0.00/3.42M [00:00<?, ?B/s]
 61%|######    | 2.09M/3.42M [00:00<00:00, 11.6MB/s]
100%|##########| 3.42M/3.42M [00:00<00:00, 18.5MB/s]
/venv/apache-tvm-py3.8/lib/python3.8/site-packages/torch/_utils.py:314: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()
  device=storage.device,
/workspace/python/tvm/relay/frontend/pytorch_utils.py:47: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
  return LooseVersion(torch_ver) > ver
/venv/apache-tvm-py3.8/lib/python3.8/site-packages/setuptools/_distutils/version.py:346: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.
  other = LooseVersion(other)

定义目标、运行时与执行器

在本教程中,我们使用 AOT 主机驱动执行器。为了在 x86 机器上对嵌入式模拟环境编译模型,我们使用 C 运行时(CRT),并使用主机微型目标。使用该设置,TVM 为 C 运行时编译可以在 x86 CPU 机器上运行的模型,可以在物理微控制器上运行的相同流程。CRT 使用 src/runtime/crt/host/main.cc 中的 main()。要使用物理硬件,请将 board 替换为另一个物理微型目标,例如 nrf5340dk_nrf5340_cpuapp 或 mps2_an521,并将平台类型更改为 Zephyr。在《为 Arduino 上的 microTVM 训练视觉模型》和《microTVM TFLite 教程》中,可以看到 更多目标示例。

target = tvm.micro.testing.get_target(platform="crt", board=None)

# 使用 C 运行时 (crt) 并通过设置 system-lib 为 True 打开静态链接
runtime = tvm.relay.backend.Runtime("crt", {"system-lib": True})

# 使用 AOT 执行器代替图或 vm 执行器。不要使用未包装的 API 或 C 风格调用
executor = Executor("aot")

编译模型

现在为目标编译模型:

with tvm.transform.PassContext(
    opt_level=3,
    config={"tir.disable_vectorize": True},
):
    module = tvm.relay.build(
        relay_mod, target=target, runtime=runtime, executor=executor, params=params
    )

创建 microTVM 项目

现在,我们已经将编译好的模型作为 IRModule 准备好,我们还需要创建一个固件项目,以便在 microTVM 中使用编译好的模型。为此,我们需要使用 Project API。

template_project_path = pathlib.Path(tvm.micro.get_microtvm_template_projects("crt"))
project_options = {"verbose": False, "workspace_size_bytes": 6 * 1024 * 1024}

temp_dir = tvm.contrib.utils.tempdir() / "project"
project = tvm.micro.generate_project(
    str(template_project_path),
    module,
    temp_dir,
    project_options,
)

构建、烧录和执行模型

接下来,我们构建 microTVM项 目并进行烧录。烧录步骤特定于物理微控制器,如果通过主机的 main.cc 模拟微控制器,或者选择 Zephyr 模拟单板作为目标,则会跳过该步骤。

project.build()
project.flash()

input_data = {input_name: tvm.nd.array(img.astype("float32"))}
with tvm.micro.Session(project.transport()) as session:
    aot_executor = tvm.runtime.executor.aot_executor.AotModule(session.create_aot_executor())
    aot_executor.set_input(**input_data)
    aot_executor.run()
    result = aot_executor.get_output(0).numpy()

查询 Synset 名称

查询在 1000 个类别 Synset 中的 top-1 的预测。

synset_url = (
    "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 = (
    "https://raw.githubusercontent.com/Cadene/"
    "pretrained-models.pytorch/master/data/"
    "imagenet_classes.txt"
)
class_path = download_testdata(class_url, "imagenet_classes.txt", 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(result)
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]))

输出结果:

Relay top-1 id: 282, class name: tiger cat
Torch top-1 id: 282, class name: tiger cat

该脚本总运行时间:(1分26.552秒)

下载 Python 源代码:micro_pytorch.py

下载 Jupyter notebook:micro_pytorch.ipynb

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

### TVM 安装指南 #### 环境准备 在安装 TVM 之前,需要确保开发环境中已经具备必要的依赖项。这些依赖通常包括编译器工具链、Python 开发包以及一些特定的库文件。对于 Linux 用户来说,可以通过包管理器来安装基础依赖;而对于 Windows 用户,则建议使用 WSL 或者 MinGW 工具链。 - **Linux/macOS**: 使用 `apt` 或 `brew` 安装基本依赖[^1]。 - **Windows**: 推荐通过 WSL2 配置 Ubuntu 子系统来进行安装[^2]。 #### 设置构建路径 TVM 提供了一个灵活的方式来定义其构建目录的位置。这可以通过设置环境变量 `TVM_BUILD_PATH` 实现: ```bash export TVM_BUILD_PATH=/path/to/custom/build/directory ``` 如果没有显式设定该变量,默认情况下 Makefile 将会尝试使用位于项目根目录下的 `build` 文件夹作为工作区[^1]。值得注意的是,此路径既可以是一个相对地址也可以是绝对定位,并支持多个以空格分割的目标位置声明。 #### 编译过程概述 以下是基于源码的一般化编译流程描述(适用于大多数类 Unix 平台),具体命令可能会因操作系统差异有所调整: 1. 获取最新版代码仓库并初始化子模块: ```bash git clone --recursive https://github.com/apache/tvm.git tvm cd tvm ``` 2. 创建专用的构建空间(如果尚未通过前述方法预设的话): ```bash mkdir build && cd build ``` 3. 利用 CMake 准备生成规则, 这里我们假设采用 Ninja 后端加速增量更新速度: ```cmake cmake .. -G"Ninja" ``` 4. 执行实际组装操作: ```bash ninja ``` 针对某些高级特性比如神经网络推理优化框架(NNPACK),还需要额外执行如下步骤以便启用它们的支持功能[^3]: ```bash git clone --recursive https://github.com/Maratyszcza/NNPACK.git cd NNPACK sed -i "s|gnu99|gnu99 -fPIC|g" CMakeLists.txt sed -i "s|gnu++11|gnu++11 -fPIC|g" CMakeLists.txt mkdir build && cd build cmake -G Ninja -D BUILD_SHARED_LIBS=ON .. ninja sudo ninja install echo "/usr/local/lib" >> /etc/ld.so.conf.d/nnpack.conf sudo ldconfig ``` #### 特殊注意事项 尽管官方文档提供了详尽指导,但在跨平台移植过程中仍可能出现兼容性挑战。例如,在 Windows 上部署 GPU 加速版本时遇到 RPC 功能失效的问题已被报告至社区论坛待进一步修复[^2]。因此,当考虑此类复杂场景应用前应充分评估潜在风险因素。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值