Vitis AI 集成

更多 TVM 中文文档可访问 →Apache TVM 是一个端到端的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。IApache TVM 中文站
**Vitis AI **是用在 Xilinx 平台(包括边缘设备和 Alveo 卡)上进行硬件加速 AI 推理的 Xilinx 开发堆栈。它由优化的 IP、工具、库、模型和示例设计组成。在设计时兼顾高效率和易用性,充分发挥了 Xilinx FPGA 和 ACAP 上 AI 加速的潜力。

TVM 中当前的 Vitis AI 流支持使用** Zynq Ultrascale+ MPSoc, Alveo Versal **平台在边缘和云端加速神经网络模型推理。支持的边缘和云深度学习处理器单元(DPU)的标识符是:

Target Board DPU ID TVM Target ID
ZCU104 DPUCZDX8G DPUCZDX8G-zcu104
ZCU102 DPUCZDX8G DPUCZDX8G-kv260
Kria KV260 DPUCZDX8G DPUCZDX8G-kv260
VCK190 DPUCVDX8G DPUCVDX8G
VCK5000 DPUCVDX8H DPUCVDX8H
U200 DPUCADF8H DPUCADF8H
U250 DPUCADF8H DPUCADF8H
U50 DPUCAHX8H / DPUCAHX8L DPUCAHX8H-u50 / DPUCAHX8L
U280 DPUCAHX8H / DPUCAHX8L DPUCAHX8H-u280 / DPUCAHX8L

有关 DPU 标识符的更多信息,参见下表:

DPU Application HW Platform Quantization Method Quantization Bitwidth Design Target
Deep LearningProcessing Unit C: CNNR: RNN AD: Alveo DDRAH: Alveo HBMVD: Versal DDR with AIE & PLZD: Zynq DDR X: DECENTI: Integer thresholdF: Float thresholdR: RNN 4: 4-bit8: 8-bit16: 16-bitM: Mixed Precision G: General purposeH: High throughputL: Low latencyC: Cost optimized

此教程介绍有关如何在不同平台(Zynq、Alveo、Versal)上使用 Vitis AI 设置 TVM 以及如何开始 编译模型 并在不同平台上执行:推理。

系统要求V

Vitis AI 系统要求页面 列出了运行 Docker 容器以及在 Alveo 卡上执行的系统要求。对于边缘设备(例如 Zynq),部署模型需要使用带有 Vitis AI 流程的 TVM 编译模型的主机,以及用于运行编译模型的边缘设备。主机系统要求与上面链接中指定的相同。

设置说明

本节介绍如何用 Vitis AI 流为云和边缘设置 TVM。支持 Vitis AI 的 TVM 是通过 Docker 容器提供的。提供的脚本和 Dockerfile 将 TVM 和 Vitis AI 编译为单个镜像。

1.克隆 TVM 仓库

  git clone --recursive https://github.com/apache/tvm.git
   cd tvm

2.构建并启动 TVM - Vitis AI Docker 容器。

   ./docker/build.sh demo_vitis_ai bash
   ./docker/bash.sh tvm.demo_vitis_ai

   # Setup inside container
   conda activate vitis-ai-tensorflow

3.用 Vitis AI(在 TVM 目录内)在容器内构建 TVM

   mkdir build
   cp cmake/config.cmake build
   cd build
   echo set(USE_LLVM ON) >> config.cmake
   echo set(USE_VITIS_AI ON) >> config.cmake
   cmake ..
   make -j$(nproc)

4.安装 TVM

   cd ../python
   pip3 install -e . --user

在这个 Docker 容器中可以为云和边缘目标编译模型。要在 docker 容器内的云 Alveo 或 Versal VCK5000 卡上运行,按照 Alveo 或者 Versal VCK5000 设置说明进行操作。分别参照 Zynq 和 Versal VCK190,为推理过程设置 Zynq 或 Versal VCK190 评估单板。

Alveo 设置

查看 Alveo 设置 获取设置信息。

设置后,通过以下方式在 Docker 容器内选择正确的 DPU:

cd /workspace
git clone --branch v1.4 --single-branch --recursive https://github.com/Xilinx/Vitis-AI.git
cd Vitis-AI/setup/alveo
source setup.sh [DPU-IDENTIFIER]

可在此页面顶部的 DPU Targets 表的第二列中找到此 DPU 标识符。

Versal VCK5000 设置

查看 VCK5000 Setup 获取设置信息。

设置后,可以通过以下方式在 Docker 容器内选择正确的 DPU:

cd /workspace
git clone --branch v1.4 --single-branch --recursive https://github.com/Xilinx/Vitis-AI.git
cd Vitis-AI/setup/vck5000
source setup.sh

Zynq 设置

除了构建 TVM - Vitis AI docker 之外,对于 Zynq 目标(DPUCZDX8G),编译阶段在主机上的 docker 内运行,不需要任何特定设置。执行模型时,首先要设置 Zynq 板,更多信息如下。

1.下载 Petalinux 镜像:

  • ZCU104
  • ZCU102
  • Kria KV260
    2.使用 Etcher 软件将镜像文件刻录到 SD 卡上。

3.将带有图像的 SD 卡插入目标单板。

4.插入电源并使用串行端口在系统上启动该单板。

5.用串口设置单板的 IP 信息。有关步骤 1 至 5 的更多信息,参阅 设置评估单板。

6.在单板上创建 4GB 的交换空间

fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile swap swap defaults 0 0" >> /etc/fstab

7.安装 hdf5 依赖(需要 30 分钟到 1 小时)

cd /tmp && \
  wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.7/src/hdf5-1.10.7.tar.gz && \
  tar -zxvf hdf5-1.10.7.tar.gz && \
  cd hdf5-1.10.7 && \
  ./configure --prefix=/usr && \
  make -j$(nproc) && \
  make install && \
  cd /tmp && rm -rf hdf5-1.10.7*

8.安装 Python 依赖

pip3 install Cython==0.29.23 h5py==2.10.0 pillow

9.安装 PyXIR

git clone --recursive --branch rel-v0.3.1 --single-branch https://github.com/Xilinx/pyxir.git
cd pyxir
sudo python3 setup.py install --use_vart_edge_dpu

10.用 Vitis AI 构建和安装 TVM

git clone --recursive https://github.com/apache/tvm
cd tvm
mkdir build
cp cmake/config.cmake build
cd build
echo set(USE_LLVM OFF) >> config.cmake
echo set(USE_VITIS_AI ON) >> config.cmake
cmake ..
make tvm_runtime -j$(nproc)
cd ../python
pip3 install --no-deps  -e .

11.在 Python shell 中检查设置是否成功:

python3 -c 'import pyxir; import tvm'

备注
可能会看到有关未找到 “cpu-tf” runtime 的警告,可以忽略。

Versal VCK190 设置

参考 Zynq 设置 设置 Versal VCK190,但在步骤 1 中参考 VCK190 镜像。其他步骤相同。

编译模型

带有 Vitis AI 流的 TVM 包含编译和推理两个阶段。在编译期间,用户可以为当前支持的云或边缘目标设备选择要编译的模型。编译模型生成的文件可用于在 推理 阶段在指定的目标设备上运行模型。目前,采用 Vitis AI 流程的 TVM 支持选定数量的 Xilinx 数据中心和边缘设备。

本节介绍在 TVM 中用 Vitis AI 编译模型的一般流程。

导入

确保导入 PyXIR 和 DPU target(为 DPUCADF8H import pyxir.contrib.target.DPUCADF8H ):

import pyxir
import pyxir.contrib.target.DPUCADF8H

import tvm
import tvm.relay as relay
from tvm.contrib.target import vitis_ai
from tvm.contrib import utils, graph_executor
from tvm.relay.op.contrib.vitis_ai import partition_for_vitis_ai

声明 Target

tvm_target = 'llvm'
dpu_target = 'DPUCADF8H' # options: 'DPUCADF8H', 'DPUCAHX8H-u50', 'DPUCAHX8H-u280', 'DPUCAHX8L', 'DPUCVDX8H', 'DPUCZDX8G-zcu104', 'DPUCZDX8G-zcu102', 'DPUCZDX8G-kv260'

带有 Vitis AI 流的 TVM 目前支持本页顶部表格中列出的 DPU targets。一旦定义了恰当的 target,就会调用 TVM 编译器来为指定的 target 构建计算图。

导入模型

导入 MXNet 模型的示例代码:

mod, params = relay.frontend.from_mxnet(block, input_shape)

对模型分区

导入模型后,用 Relay API 为 DPU target 注释 Relay 表达式,并对计算图进行分区。

mod = partition_for_vitis_ai(mod, params, dpu=dpu_target)

构建模型

将分区模型传给 TVM 编译器,然后生成 TVM Runtime 的 runtime 库。

export_rt_mod_file = os.path.join(os.getcwd(), 'vitis_ai.rtmod')
build_options = {
    'dpu': dpu_target,
    'export_runtime_module': export_rt_mod_file
}
with tvm.transform.PassContext(opt_level=3, config={'relay.ext.vitis_ai.options': build_options}):
    lib = relay.build(mod, tvm_target, params=params)

量化模型

为了用 Vitis AI DPU 加速器来加速神经网络模型的推理,通常要对模型预先量化。在 TVM - Vitis AI 流中,利用动态量化来替代此预处理步骤。在这个流中,可用典型的推理执行调用(module.run)使用提供的前 N 个输入动态量化模型(参见更多信息如下),而不需要预先量化模型。这将设置和校准 Vitis-AI DPU,为后面所有输入加速推理。

注意:边缘流与推理中解释的流略有不同,边缘流在前 N 个输入后模型被量化和编译,但推理不会加速,并且它可以移动到边缘设备进行部署。查看下面的 在 Zynq 上运行 部分了解更多信息。

module = graph_executor.GraphModule(lib["default"](tvm.cpu()))

# 前 N 个(默认 = 128)输入用于量化校准,并在 CPU 上执行
# 可以通过设置 “PX_QUANT_SIZE” 来更改此配置(例如,导出 PX_QUANT_SIZE=64)
for i in range(128):
   module.set_input(input_name, inputs[i])
   module.run()

用于量化的图像数量默认设置为 128,可以使用 PX_QUANT_SIZE 环境变量更改动态量化的图像数量。例如,在调用编译脚本之前在终端中执行如下命令,将量化校准数据集减少到八幅图像。

export PX_QUANT_SIZE=8

最后将 TVM 编译器的编译输出存储在磁盘上,方便在目标设备上运行模型。云 DPU(Alveo 和 VCK5000)的情况如下:

lib_path = "deploy_lib.so"
lib.export_library(lib_path)

对于边缘 target(Zynq 和 VCK190),必须为 aarch64 重建。因此首先必须正常导出模块,并同时序列化 Vitis AI runtime 模块(vitis_ai.rtmod)。之后再次加载此 runtime 模块,为 aarch64 重建和导出。

temp = utils.tempdir()
lib.export_library(temp.relpath("tvm_lib.so"))

# 为 aarch64 target 构建和导出库
tvm_target = tvm.target.arm_cpu('ultra96')
lib_kwargs = {
   'fcompile': contrib.cc.create_shared,
   'cc': "/usr/aarch64-linux-gnu/bin/ld"
}

build_options = {
    'load_runtime_module': export_rt_mod_file
}
with tvm.transform.PassContext(opt_level=3, config={'relay.ext.vitis_ai.options': build_options}):
     lib_edge = relay.build(mod, tvm_target, params=params)

lib_edge.export_library('deploy_lib_edge.so', **lib_kwargs)

使用 TVM 和 Vitis AI 编译模型的教程到此结束,有关如何运行已编译的模型,参阅下一节。

推理

带有 Vitis AI 流的 TVM 包含编译和推理两个阶段,在编译期间,用户可以选择为当前支持的任何目标设备编译模型。编译模型后生成的文件可用于在推理阶段在目标设备上运行模型。

查看 在 Alveo 和 VCK5000 上运行 以及 **在 Zynq 和 VCK190 上运行 **部分,分别在云加速卡和边缘板上进行推理。

在 Alveo 和 VCK5000 上运行

按照编译模型部分中的步骤,可以在 Docker 内的新输入上执行如下命令以加速推理:

module.set_input(input_name, inputs[i])
module.run()

或者加载导出的 runtime 模块(在 编译模型 中导出的 deploy_lib.so):

import pyxir
import tvm
from tvm.contrib import graph_executor

dev = tvm.cpu()

# input_name = ...
# input_data = ...

# 将模块加载到内存
lib = tvm.runtime.load_module("deploy_lib.so")

module = graph_executor.GraphModule(lib["default"](dev))
module.set_input(input_name, input_data)
module.run()

在 Zynq 和 VCK190 上运行

开始前按照 Zynq 或 Versal VCK190 设置说明进行设置。

在单板上运行模型之前,需要为目标评估单板编译模型,并将编译后的模型传输到板上。如何编译模型,参阅 编译模型 部分。

之后将编译好的模型(deploy_lib_edge.so)传输到评估单板,然后可以在板上使用典型的「load_module」和「module.run」API 来执行。确保以 root 身份运行脚本(在终端中执行 su 登录到 root)。

备注
不要在运行脚本(import pyxir.contrib.target.DPUCZDX8G)中导入 PyXIR DPU targets。

import pyxir
import tvm
from tvm.contrib import graph_executor

dev = tvm.cpu()

# input_name = ...
# input_data = ...

# 将模块加载到内存
lib = tvm.runtime.load_module("deploy_lib_edge.so")

module = graph_executor.GraphModule(lib["default"](dev))
module.set_input(input_name, input_data)
module.run()

你可能感兴趣的:(TVM,人工智能,TVM)