• 文档 >
  • torch.compiler >
  • AOTInductor:Torch.Export 导出模型的即时编译
快捷键

AOTInductor:Torch.Export 导出模型的即时编译 ¶

警告

AOTInductor 及其相关特性处于原型状态,可能存在向后兼容性破坏的变更。

AOTInductor 是 TorchInductor 的专用版本,旨在处理导出的 PyTorch 模型,优化它们,并生成共享库以及其他相关工件。这些编译工件专门用于部署在非 Python 环境中,这些环境通常用于服务器端推理部署。

在本教程中,您将深入了解将 PyTorch 模型导出、编译成工件以及使用 C++进行模型预测的过程。

模型编译

使用 AOTInductor 编译模型时,我们首先需要使用 torch.export.export() 将给定的 PyTorch 模型捕获到计算图中。torch.export 提供了关于捕获的 IR 的严格规范,这是 AOTInductor 所依赖的。

然后,我们将使用 torch._inductor.aoti_compile_and_package() 使用 TorchInductor 编译导出的程序,并将编译后的工件保存到一个包中。

注意

如果您的机器上有一个启用 CUDA 的设备并且您已安装了具有 CUDA 支持的 PyTorch,以下代码将编译模型为 CUDA 执行的可共享库。否则,编译的工件将在 CPU 上运行。为了在 CPU 推理期间获得更好的性能,建议在运行下面的 Python 脚本之前启用冻结,通过设置 export TORCHINDUCTOR_FREEZING=1 。在具有 Intel® GPU 的环境中也有相同的行为。

import os
import torch

class Model(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = torch.nn.Linear(10, 16)
        self.relu = torch.nn.ReLU()
        self.fc2 = torch.nn.Linear(16, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        x = self.sigmoid(x)
        return x

with torch.no_grad():
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model = Model().to(device=device)
    example_inputs=(torch.randn(8, 10, device=device),)
    batch_dim = torch.export.Dim("batch", min=1, max=1024)
    # [Optional] Specify the first dimension of the input x as dynamic.
    exported = torch.export.export(model, example_inputs, dynamic_shapes={"x": {0: batch_dim}})
    # [Note] In this example we directly feed the exported module to aoti_compile_and_package.
    # Depending on your use case, e.g. if your training platform and inference platform
    # are different, you may choose to save the exported model using torch.export.save and
    # then load it back using torch.export.load on your inference platform to run AOT compilation.
    output_path = torch._inductor.aoti_compile_and_package(
        exported,
        # [Optional] Specify the generated shared library path. If not specified,
        # the generated artifact is stored in your system temp directory.
        package_path=os.path.join(os.getcwd(), "model.pt2"),
    )

在这个示例中, Dim 参数被用来指定输入变量“x”的第一个维度为动态。值得注意的是,编译库的路径和名称未指定,导致共享库被存储在临时目录中。为了从 C++端访问此路径,我们将其保存到文件中,以便在 C++代码中稍后检索。

Python 中的推理

部署编译工件进行推理有多种方式,其中之一是使用 Python。我们提供了一个方便的实用 API torch._inductor.aoti_load_package() ,用于加载和运行工件,如下例所示:

import os
import torch

device = "cuda" if torch.cuda.is_available() else "cpu"
model = torch._inductor.aoti_load_package(os.path.join(os.getcwd(), "model.pt2"))
print(model(torch.randn(8, 10, device=device)))

推理时的输入应与导出时的输入具有相同的大小、数据类型和步长。

C++中的推理

接下来,我们使用以下示例 C++文件 inference.cpp 来加载编译后的工件,使我们能够在 C++环境中直接进行模型预测。

#include <iostream>
#include <vector>

#include <torch/torch.h>
#include <torch/csrc/inductor/aoti_package/model_package_loader.h>

int main() {
    c10::InferenceMode mode;

    torch::inductor::AOTIModelPackageLoader loader("model.pt2");
    // Assume running on CUDA
    std::vector<torch::Tensor> inputs = {torch::randn({8, 10}, at::kCUDA)};
    std::vector<torch::Tensor> outputs = loader.run(inputs);
    std::cout << "Result from the first inference:"<< std::endl;
    std::cout << outputs[0] << std::endl;

    // The second inference uses a different batch size and it works because we
    // specified that dimension as dynamic when compiling model.pt2.
    std::cout << "Result from the second inference:"<< std::endl;
    // Assume running on CUDA
    std::cout << loader.run({torch::randn({1, 10}, at::kCUDA)})[0] << std::endl;

    return 0;
}

构建 C++文件时,您可以使用提供的 CMakeLists.txt 文件,该文件自动化调用 python model.py 进行 AOT 编译模型,并将 inference.cpp 编译成名为 aoti_example 的可执行二进制文件。

cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
project(aoti_example)

find_package(Torch REQUIRED)

add_executable(aoti_example inference.cpp model.pt2)

add_custom_command(
    OUTPUT model.pt2
    COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/model.py
    DEPENDS model.py
)

target_link_libraries(aoti_example "${TORCH_LIBRARIES}")
set_property(TARGET aoti_example PROPERTY CXX_STANDARD 17)

如果目录结构类似于以下,则可以执行后续命令来构建二进制文件。请注意, CMAKE_PREFIX_PATH 变量对于 CMake 定位 LibTorch 库至关重要,并且它应该设置为绝对路径。请务必注意,您的路径可能与示例中的路径不同。

aoti_example/
    CMakeLists.txt
    inference.cpp
    model.py
$ mkdir build
$ cd build
$ CMAKE_PREFIX_PATH=/path/to/python/install/site-packages/torch/share/cmake cmake ..
$ cmake --build . --config Release

build 目录中生成 aoti_example 二进制文件后,执行它将显示类似于以下的结果:

$ ./aoti_example
Result from the first inference:
0.4866
0.5184
0.4462
0.4611
0.4744
0.4811
0.4938
0.4193
[ CUDAFloatType{8,1} ]
Result from the second inference:
0.4883
0.4703
[ CUDAFloatType{2,1} ]

故障排除

以下是调试 AOT Inductor 的一些有用工具。

要启用输入的运行时检查,请设置环境变量 AOTI_RUNTIME_CHECK_INPUTS 为 1。如果编译模型的输入与导出时使用的输入在大小、数据类型或步幅上不同,将引发 RuntimeError。

API 参考指南

torch._inductor.aoti_compile_and_package(exported_program, _deprecated_unused_args=None, _deprecated_unused_kwargs=None, *, package_path=None, inductor_configs=None)[source][source]

使用 AOTInductor 编译导出的程序,并将其打包成由输入 package_path 指定的 .pt2 文件。要加载该包,您可以调用 torch._inductor.aoti_load_package(package_path)

以下是一个示例用法:

ep = torch.export.export(M(), ...)
aoti_file = torch._inductor.aoti_compile_and_package(
    ep, package_path="my_package.pt2"
)
compiled_model = torch._inductor.aoti_load_package("my_package.pt2")

要将多个模型编译并保存为单个 .pt2 工件,您可以执行以下操作:

ep1 = torch.export.export(M1(), ...)
aoti_file1 = torch._inductor.aot_compile(
    ep1, ..., options={"aot_inductor.package": True}
)
ep2 = torch.export.export(M2(), ...)
aoti_file2 = torch._inductor.aot_compile(
    ep2, ..., options={"aot_inductor.package": True}
)

from torch._inductor.package import package_aoti, load_package

package_aoti("my_package.pt2", {"model1": aoti_file1, "model2": aoti_file2})

compiled_model1 = load_package("my_package.pt2", "model1")
compiled_model2 = load_package("my_package.pt2", "model2")
参数:
  • exported_program(ExportedProgram)- 通过 torch.export 调用创建的导出程序

  • package_path(可选[FileLike])- 生成.pt2 工件的可选指定路径。

  • 电感器配置(可选[dict[str, Any]])- 可选的配置字典,用于控制电感器。

返回值:

生成实体的路径

返回类型:

str

torch._inductor.aoti_load_package(path, run_single_threaded=False)[source][source]

从 PT2 包中加载模型。

如果将多个模型打包到 PT2 中,这将加载默认模型。要加载特定模型,可以直接调用加载 API

from torch._inductor.package import load_package

compiled_model1 = load_package("my_package.pt2", "model1")
compiled_model2 = load_package("my_package.pt2", "model2")
参数:
  • 路径(FileLike)- .pt2 包的路径

  • run_single_threaded(布尔值)- 模型是否应在没有线程同步逻辑的情况下运行。这有助于避免与 CUDAGraphs 冲突

返回类型:

任何


© 版权所有 PyTorch 贡献者。

使用 Sphinx 构建,主题由 Read the Docs 提供。

文档

查看 PyTorch 的全面开发者文档

查看文档

教程

深入了解初学者和高级开发者的教程

查看教程

资源

查找开发资源并获得您的疑问解答

查看资源