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

此命令同时构建 TVMonnxruntime-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 的依赖项
    1. 通过命令行在 windows 上安装 asm 编译器 (nasm)
      winget install nasm -i
      

                将其添加到 PATH(Windows GUI 的说明可以在 此处 看到)或通过 cmd

      set PATH="%PATH%;C:\Program Files\NASM"
      

                在提示符命令行中使用 nasm --version 进行检查。
            

    2. 此处 通过 msi 文件在 windows 上安装 openssl。将带有可执行文件的目录(例如“C:\Program Files\OpenSSL-Win64\bin”)的路径添加到 PATH(请参阅以上说明)。
                在提示符命令行中使用 openssl version 进行检查。

为了使用 NVIDIA GPU(可选),应安装 CUDA 和 cuDNN。

  • CUDA:通过 链接 安装 CUDA。
  • cuDNN:从 此处 下载 cuDNN 安装程序。为相应的 CUDA v11.* 选择 v8.*,解压缩它,然后按如下方式移动 cuDNN 文件
    1. [解压缩的目录]\bin\ → C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\bin
    2. [解压缩的目录]\include\ → C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\include
    3. [解压缩的目录]\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 参数中传递的文件夹中搜索该文件。
  • targettarget_host 是类似 TVM 的字符串(例如“llvm –mcpu=avx2”)。当使用加速器时,target 可能是类似 cuda 的东西,而 target_host 可能是 llvm -mtriple=x86_64-linux-gnu
  • opt_level 是 TVM 优化级别。默认值为 3
  • freeze_weights 表示所有模型权重都保留在编译阶段,否则每次推理都会下载它们。建议使用 True 值以获得最佳性能。默认值为 true。
  • to_nhwc 开启特殊的模型转换,特别是数据布局,Octomizer 被使用。它允许正确处理从 Octomizer 获得的调优日志。默认情况下为 false。
  • tuning_type 定义了正在使用的 TVM 调优日志的类型,可以设置为 AutoTVM(第一代自动调优日志)或 Ansor(第二代自动调优日志)。默认情况下,此选项设置为 AutoTVM
  • tuning_file_path 是 AutoTVM 或 Ansor 调优文件的路径,该文件为给定模型和目标提供最佳性能的规范。(有关更多详细信息,请参见下文)。

TVM 仅支持具有固定图的模型。如果您的模型的输入形状中具有未知维度(不包括批大小),则必须使用 input_namesinput_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