TVM 执行提供程序
TVM 是一个基于 Apache TVM 构建的 ONNX Runtime 执行提供程序。它允许 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,由于其版本为 2.13.02,apt-get install nasm
不够,请参阅 此处 从源代码安装的说明。
此外,当前实现支持 TVM EP 的 NVidia GPU
。目前,您只能使用支持 CUDA Toolkit 的 NVidia GPU
。为此,请确保您已安装 NVidia 驱动程序和 CUDA Toolkit。更详细的说明可在 官方页面 上找到。
克隆此仓库。为了构建 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 (TVM with CUDA support)
./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 的路径已包含在环境变量中。默认情况下,它应该会被添加。安装后,在命令行 (cmd) 中使用
git --version
检查 git。 - CMake:使用 此链接 下载并安装 CMake。推荐使用 msi 文件。在 cmd 中使用
cmake --version
验证 CMake 安装。 - Visual Studio:从 此处 下载并分别安装 Visual Studio 20** Community 和 Visual Studio Build Tools。建议不要更改默认安装路径。选择“使用 C++ 的桌面开发”工作负载,并确保同时选中“MSVC [当代版本] C++ 构建工具”和“Windows 10 SDK”两个选项。
- Python:从 此处 下载并安装 Python 3.*。请务必勾选“将 Python 添加到 PATH”选项,这样安装程序会将 Python 目录直接包含到环境变量中。安装后,在 cmd 中使用
python
检查 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
在 cmd 中使用 nvcc --version
验证 CUDA 安装。
从源代码构建带 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 包,因为 TVM EP 内部使用了它的 python API
它可能看起来像这样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 依赖这些日志来最大化模型性能。您可以通过以下方式获取模型的这些日志
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 平台 获得或直接编译(有关模型编译的更多信息,请参阅 ResNet50 推理与 TVM EP 示例笔记本 中的支持预编译模型部分)。
为了使用预编译模型,只需要传递两个选项
- 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