更多 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()