TVM 执行提供程序
TVM 是 ONNX Runtime 的执行提供程序,构建于 Apache TVM 之上。它使 ONNX Runtime 用户能够利用 Apache TVM 模型优化。TVM EP 目前处于“预览”状态。它已经过测试,可在 Linux 和 Windows 上的一些模型上工作,但不能在 MacOS 上工作。
目录
使用 TVM 执行提供程序构建 ONNX Runtime
Linux
在 Ubuntu/Debian 等 Linux 操作系统上安装最基本的前提条件
apt-get install -y python3 python3-dev python3-pip python3-setuptools gcc libtinfo-dev zlib1g-dev build-essential cmake libedit-dev libxml2-dev llvm-12
pip3 install numpy decorator attrs nasm
注意:由于带有 TVM EP 的 ONNX Runtime 是使用 Intel ipp-crypto 库构建的,因此有新的要求。编译器 gcc(和 g++)版本应等于或高于 8.2。nasm 版本应为 2.14.02 或更高版本。nasm 版本过小的问题可以在 此处 或 此处 看到。对于 ubuntu LTS 18,apt-get install nasm
不够用,因为它具有 2.13.02 版本,请参阅 此处 从源代码安装的说明。
此外,当前的实现具有针对 TVM EP 的 NVidia GPU
支持。目前,您只能将 NVidia GPU
与 CUDA 工具包支持一起使用。为此,请确保您已安装 NVidia 驱动程序和 CUDA 工具包。更详细的说明可以在 官方页面 上找到。
克隆此仓库。为了构建 ONNXRT,您需要安装 CMake 3.18 或更高版本。在 Ubuntu 20.04 中,您可以使用以下命令安装最新版本的 CMake
sudo apt-get update
sudo apt-get install gpg wget
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
sudo apt-get update
sudo rm /usr/share/keyrings/kitware-archive-keyring.gpg
sudo apt-get install kitware-archive-keyring
sudo apt-get install cmake
构建 ONNX Runtime (TVM x86)
./build.sh --config Release --enable_pybind --build_wheel --parallel --skip_tests --skip_onnx_tests --use_tvm
构建 ONNX Runtime (支持 CUDA 的 TVM)
./build.sh --config Release --enable_pybind --build_wheel --parallel --skip_tests --skip_onnx_tests --use_tvm --tvm_cuda_runtime
此命令同时构建 TVM
和 onnxruntime-tvm
。它为每个项目创建两个 wheel 包。构建 ONNX Runtime 的 python API,而不是使用标准包。以下给出了相关说明。
TVM 的包
cd <path_to_onnx_runtime>
python3 -m pip uninstall tvm -y
whl_path=$(find ./build/<OS_NAME>/Release/_deps/tvm-src/python/dist -name "*.whl")
python3 -m pip install $whl_path
TVM EP 的包
cd <path_to_onnx_runtime>
python3 -m pip uninstall onnxruntime onnxruntime-tvm -y
whl_path=$(find ./build/<OS_NAME>/Release/dist -name "*.whl")
python3 -m pip install $whl_path
或者,您可以设置 PYTHONPATH
以告知 python 在哪里可以找到 ONNXRT 库和 TVM 库。
export PYTHONPATH=<path_to_onnx_runtime>/build/<OS_NAME>/Release:${PYTHONPATH}
export PYTHONPATH=<path_to_onnx_runtime>/build/<OS_NAME>/Release/_deps/tvm-src/python:${PYTHONPATH}
Windows
在 Windows 上安装最基本的前提条件:Git、CMake、Visual Studio、Python、LLVM
- Git:从 此处 下载 Git for Windows 并安装它。请确保 git.exe 路径包含在环境变量中。默认情况下,应已添加。要在安装后检查 git,请在命令行 (cmd) 中使用
git --version
。 - CMake:使用此链接下载并安装 CMake。建议使用 msi 文件。要验证 CMake 安装,请在 cmd 中使用
cmake --version
。 - Visual Studio:从 此处 下载并分别安装 Visual Studio 20** Community 和 Visual Studio Build Tools。建议不要更改默认安装路径。选择“使用 C++ 的桌面开发”工作负载,并确保选中“MSVC [当代版本] C++ 生成工具”和“Windows 10 SDK”这两个选项。
- Python:从 此处 下载 Python 3.* 并安装它。请检查“Add Python to PATH”选项,以便安装程序将 Python 目录直接包含到环境变量中。要在安装后检查 python,请从 cmd 使用
python
。预期输出类似于以下内容Python 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>>
使用
quit()
退出 python 界面。 - LLVM:编译器对于纯 ONNX Runtime 安装不是必需的,但默认情况下对于 TVM EP 是必需的。
git clone --depth 1 --branch release/11.x https://github.com/llvm/llvm-project.git cmake -S llvm -B build -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" -DLLVM_TARGETS_TO_BUILD=X86 -Thost=x64 -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" cmake --build ./build --config Release
- ipp-crypto 的依赖项
- 通过命令行在 windows 上安装 asm 编译器 (nasm)
winget install nasm -i
将其添加到 PATH(Windows GUI 的说明可以在 此处 看到)或通过 cmd
set PATH="%PATH%;C:\Program Files\NASM"
在提示符命令行中使用
nasm --version
进行检查。
- 从 此处 通过 msi 文件在 windows 上安装 openssl。将带有可执行文件的目录(例如“C:\Program Files\OpenSSL-Win64\bin”)的路径添加到 PATH(请参阅以上说明)。
在提示符命令行中使用openssl version
进行检查。
- 通过命令行在 windows 上安装 asm 编译器 (nasm)
为了使用 NVIDIA GPU(可选),应安装 CUDA 和 cuDNN。
- CUDA:通过 链接 安装 CUDA。
- cuDNN:从 此处 下载 cuDNN 安装程序。为相应的 CUDA v11.* 选择 v8.*,解压缩它,然后按如下方式移动 cuDNN 文件
- [解压缩的目录]\bin\ → C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\bin
- [解压缩的目录]\include\ → C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\include
- [解压缩的目录]\lib\ → C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\lib
要验证 CUDA 安装,请在 cmd 中使用 nvcc --version
。
从源代码构建带有 TVM 执行提供程序的 ONNX Runtime
- 使用命令行并从 github 克隆源代码
git clone --recursive https://github.com/Microsoft/onnxruntime cd onnxruntime
- CPU 构建
build.bat --config Release --enable_pybind --build_wheel --skip_tests --parallel --use_tvm --skip_onnx_tests --cmake_generator "Visual Studio 17 2022" --llvm_config <path_to_llvm_root>/build/Release/bin/llvm-config.exe
- GPU 构建
build.bat --config Release --enable_pybind --build_wheel --skip_tests --parallel --use_tvm --skip_onnx_tests --cmake_generator "Visual Studio 17 2022" --llvm_config <path_to_llvm_root>/build/Release/bin/llvm-config.exe --use_cuda --cudnn_home “C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.*” --cuda_home “C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.*”
在两种情况(CPU、GPU)下,cmake 生成器都有以下选项:“Visual Studio 15 2017”、“Visual Studio 16 2019”、“Visual Studio 17 2022”和“Ninja”
- 安装 ONNX Runtime 的 python wheel 包
包的默认路径是<path_to_onnxruntime_root>/build/Windows/Release/Release/dist
。请注意,它与 Linux 上包的路径不同。在安装之前,检查 wheel 包的名称并使用相应的包。它可能看起来像下面这样python -m pip install .\onnxruntime\build\Windows\Release\Release\dist\onnxruntime_tvm-1.6.0-cp37-cp37m-win_amd64.whl
- 安装 TVM 的 python wheel 包,因为它的 python API 在 TVM EP 内部使用
它可能看起来像下面这样python -m pip install .\onnxruntime\build\Windows\Release\_deps\tvm-src\python\dist\tvm-0.9.dev1728+g3425ed846-cp39-cp39-win_amd64.whl
- 通过 python 脚本验证结果。注意:python 不应从包含 'onnxruntime' 目录的目录启动,以获得正确的结果
import onnxruntime print(onnxruntime.__version__) print(onnxruntime.get_device()) print(onnxruntime.get_available_providers())
- 卸载步骤
pip uninstall onnxruntime-tvm
配置选项
TVM Executor Provider 可以使用以下提供程序选项进行配置
po = [dict(executor=tvm_executor_type,
so_folder=folder_with_pretuned_files,
check_hash=check_hash,
hash_file_path=hash_file_path,
target=client_target,
target_host=client_target_host,
opt_level=client_opt_level,
freeze_weights=freeze,
to_nhwc=layout_transform,
tuning_type=tvm_optimizer_type,
tuning_file_path=client_tuning_logfile,
input_names = input_names_str,
input_shapes = input_shapes_str)]
tvm_session = onnxruntime.InferenceSession(model_path, providers=["TvmExecutionProvider"], provider_options=po)
executor
是 TVM 使用的执行器类型。有两种类型可供选择:GraphExecutor 和 VirtualMachine,它们分别对应于“graph”和“vm”标签。默认情况下使用 VirtualMachine。so_folder
是包含模型调优后获得的一组文件(.ro-、.so/.dll 文件和权重)的文件夹的路径。它使用这些文件进行执行器编译,而不是 onnx 模型。但后者仍然是 ONNX Runtime 所必需的。check_hash
表示有必要对在so_folder
参数中获得的模型执行 HASH 检查。默认情况下为False
。hash_file_path
是文件的路径,该文件包含针对 ONNX 模型的预计算 HASH,该模型是调优的结果,位于so_folder
参数传递的路径中。如果传递了空字符串作为此值,则将在so_folder
参数中传递的文件夹中搜索该文件。target
和target_host
是类似 TVM 的字符串(例如“llvm –mcpu=avx2”)。当使用加速器时,target 可能是类似cuda
的东西,而 target_host 可能是llvm -mtriple=x86_64-linux-gnu
opt_level
是 TVM 优化级别。默认值为 3freeze_weights
表示所有模型权重都保留在编译阶段,否则每次推理都会下载它们。建议使用 True 值以获得最佳性能。默认值为 true。to_nhwc
开启特殊的模型转换,特别是数据布局,Octomizer 被使用。它允许正确处理从 Octomizer 获得的调优日志。默认情况下为 false。tuning_type
定义了正在使用的 TVM 调优日志的类型,可以设置为AutoTVM
(第一代自动调优日志)或Ansor
(第二代自动调优日志)。默认情况下,此选项设置为AutoTVM
。tuning_file_path
是 AutoTVM 或 Ansor 调优文件的路径,该文件为给定模型和目标提供最佳性能的规范。(有关更多详细信息,请参见下文)。
TVM 仅支持具有固定图的模型。如果您的模型的输入形状中具有未知维度(不包括批大小),则必须使用 input_names
和 input_shapes
提供程序选项提供形状。以下是必须传递给 provider_options
的示例
input_names = "input_1 input_2"
input_shapes = "[1 3 224 224] [1 2]"
性能调优
TVM 通过自动化调优过程优化机器学习模型,该过程生成特定于目标硬件架构的模型变体。此过程还会生成 TVM EP 依赖的“调优日志”以最大化模型性能。这些日志可以通过使用此处描述的 TVM 为您的模型获取
AutoTVM: https://tvm.apache.ac.cn/docs/how_to/tune_with_autotvm/index.html
或
Ansor (自动调度): https://tvm.apache.ac.cn/docs/how_to/tune_with_autoscheduler/index.html
将 TVM EP 与 TVM 调优日志一起使用还需要用户关闭 ONNX Runtime 预处理。为此,可以使用以下 SessionOptions()
so = onnxruntime.SessionOptions()
so.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_DISABLE_ALL
tvm_session = onnxruntime.InferenceSession(model_path, sess_options=so, providers=["TvmExecutionProvider"], provider_options=po)
使用预编译模型
也可以使用预编译模型。
可以使用 OctoML 平台 获取编译后的模型,也可以直接编译(有关模型编译的更多信息,请参见 带有 TVM EP 的 ResNet50 推理示例笔记本 中的 支持预编译模型 部分)。
为了使用预编译模型,只需传递两个选项
- executor -
vm
(VirtualMachine
) 必须用作值(GraphExecutor
不支持此功能); - so_folder - 作为值,您必须传递预编译模型文件所在的目录的路径。
- check_hash -(可选)如果您想检查哈希,则必须传递
True
作为值。 - hash_file_path -(可选)默认情况下,将在
so_folder
参数中传递的目录中搜索包含已调优模型哈希的文件。如果您想指定不同的位置,则必须传递包含所需哈希的文件的路径作为值。
您可以在上面的 配置选项 部分中阅读有关这些选项的更多信息。
示例
已知问题
- 目前,TVM EP 仅在 UNIX/Linux 和 Windows 系统上经过验证。
- 在 ONNX 和 Google protobuf 之间发现了一些兼容性问题。
AttributeError: module 'google.protobuf.internal.containers' has no attribute 'MutableMapping'
。这通常发生在 protobuf 版本 >= 3.19.0 和 ONNX 版本 <= 1.8.1 的任何 python 脚本中的import onnx
期间。要解决此问题,可以单独或一起重新安装 Google protobuf 和 ONNX,使用pip3 uninstall onnx -y pip3 install onnx==1.10.1 pip3 uninstall protobuf -y pip3 install protobuf==3.19.1
已发现以下 ONNX 和 protobuf 版本对兼容
- 3.17.3 和 1.8.0
- 3.19.1 和 1.10.1