• 文档 >
  • 使用 XNNPACK 后端构建和运行 ExecuTorch
快捷方式

使用 XNNPACK 后端构建和运行 ExecuTorch

以下教程将使您熟悉如何利用 ExecuTorch XNNPACK 委托来加速使用 CPU 硬件的 ML 模型。它将介绍如何导出模型并将其序列化为二进制文件,以 XNNPACK 委托后端为目标,并在受支持的目标平台上运行模型。为了快速开始,请使用 ExecuTorch 仓库中的脚本,其中包含关于导出和为一些示例模型生成二进制文件的说明,演示了整个流程。

您将在本教程中学到什么

在本教程中,您将学习如何导出 XNNPACK 降低的模型并在目标平台上运行它

在开始之前,建议您先阅读以下内容

将模型降低到 XNNPACK

import torch
import torchvision.models as models

from torch.export import export, ExportedProgram
from torchvision.models.mobilenetv2 import MobileNet_V2_Weights
from executorch.backends.xnnpack.partition.xnnpack_partitioner import XnnpackPartitioner
from executorch.exir import EdgeProgramManager, ExecutorchProgramManager, to_edge_transform_and_lower
from executorch.exir.backend.backend_api import to_backend


mobilenet_v2 = models.mobilenetv2.mobilenet_v2(weights=MobileNet_V2_Weights.DEFAULT).eval()
sample_inputs = (torch.randn(1, 3, 224, 224), )

exported_program: ExportedProgram = export(mobilenet_v2, sample_inputs)
edge: EdgeProgramManager = to_edge_transform_and_lower(
    exported_program,
    partitioner=[XnnpackPartitioner()],
)

我们将通过 MobileNetV2 预训练模型(从 TorchVision 库下载)的示例来讲解。模型降低的流程在导出模型 to_edge 后开始。我们调用 to_backend API,并使用 XnnpackPartitioner。分区器识别适合 XNNPACK 后端委托使用的子图。之后,识别出的子图将使用 XNNPACK Delegate flatbuffer 模式进行序列化,并且每个子图将被替换为对 XNNPACK Delegate 的调用。

>>> print(edge.exported_program().graph_module)
GraphModule(
  (lowered_module_0): LoweredBackendModule()
  (lowered_module_1): LoweredBackendModule()
)



def forward(self, b_features_0_1_num_batches_tracked, ..., x):
    lowered_module_0 = self.lowered_module_0
    lowered_module_1 = self.lowered_module_1
    executorch_call_delegate_1 = torch.ops.higher_order.executorch_call_delegate(lowered_module_1, x);  lowered_module_1 = x = None
    getitem_53 = executorch_call_delegate_1[0];  executorch_call_delegate_1 = None
    aten_view_copy_default = executorch_exir_dialects_edge__ops_aten_view_copy_default(getitem_53, [1, 1280]);  getitem_53 = None
    aten_clone_default = executorch_exir_dialects_edge__ops_aten_clone_default(aten_view_copy_default);  aten_view_copy_default = None
    executorch_call_delegate = torch.ops.higher_order.executorch_call_delegate(lowered_module_0, aten_clone_default);  lowered_module_0 = aten_clone_default = None
    getitem_52 = executorch_call_delegate[0];  executorch_call_delegate = None
    return (getitem_52,)

我们在上面打印了降低后的图,以显示插入的新节点,这些节点用于调用 XNNPACK 委托。委托给 XNNPACK 的子图是每个调用点的第一个参数。可以观察到,大部分的 convolution-relu-add 块和 linear 块都能够委托给 XNNPACK。我们还可以看到未能降低到 XNNPACK 委托的运算符,例如 cloneview_copy

exec_prog = edge.to_executorch()

with open("xnnpack_mobilenetv2.pte", "wb") as file:
    exec_prog.write_to_file(file)

降低到 XNNPACK Program 后,我们可以为 executorch 准备它,并将模型保存为 .pte 文件。.pte 是一种二进制格式,用于存储序列化的 ExecuTorch 图。

将量化模型降低到 XNNPACK

XNNPACK 委托也可以执行对称量化模型。要了解量化流程并学习如何量化模型,请参考 自定义量化 注释。为了本教程的目的,我们将利用方便地添加到 executorch/executorch/examples 文件夹中的 quantize() python 辅助函数。

from torch.export import export_for_training
from executorch.exir import EdgeCompileConfig, to_edge_transform_and_lower

mobilenet_v2 = models.mobilenetv2.mobilenet_v2(weights=MobileNet_V2_Weights.DEFAULT).eval()
sample_inputs = (torch.randn(1, 3, 224, 224), )

mobilenet_v2 = export_for_training(mobilenet_v2, sample_inputs).module() # 2-stage export for quantization path

from torch.ao.quantization.quantize_pt2e import convert_pt2e, prepare_pt2e
from torch.ao.quantization.quantizer.xnnpack_quantizer import (
    get_symmetric_quantization_config,
    XNNPACKQuantizer,
)


def quantize(model, example_inputs):
    """This is the official recommended flow for quantization in pytorch 2.0 export"""
    print(f"Original model: {model}")
    quantizer = XNNPACKQuantizer()
    # if we set is_per_channel to True, we also need to add out_variant of quantize_per_channel/dequantize_per_channel
    operator_config = get_symmetric_quantization_config(is_per_channel=False)
    quantizer.set_global(operator_config)
    m = prepare_pt2e(model, quantizer)
    # calibration
    m(*example_inputs)
    m = convert_pt2e(m)
    print(f"Quantized model: {m}")
    # make sure we can export to flat buffer
    return m

quantized_mobilenetv2 = quantize(mobilenet_v2, sample_inputs)

量化需要两阶段导出。首先,我们使用 export_for_training API 在将模型提供给 quantize 实用程序函数之前捕获模型。在执行量化步骤之后,我们现在可以利用 XNNPACK 委托来降低量化的导出模型图。从这里开始,步骤与非量化模型降低到 XNNPACK 的步骤相同。

# Continued from earlier...
edge = to_edge_transform_and_lower(
    export(quantized_mobilenetv2, sample_inputs),
    compile_config=EdgeCompileConfig(_check_ir_validity=False),
    partitioner=[XnnpackPartitioner()]
)

exec_prog = edge.to_executorch()

with open("qs8_xnnpack_mobilenetv2.pte", "wb") as file:
    exec_prog.write_to_file(file)

使用 aot_compiler.py 脚本进行降低

我们还提供了一个脚本来快速降低和导出一些示例模型。您可以运行该脚本来生成降低后的 fp32 和量化模型。此脚本仅为方便起见而使用,并执行与前两节中列出的步骤相同的所有步骤。

python -m examples.xnnpack.aot_compiler --model_name="mv2" --quantize --delegate

请注意上面的示例,

  • -—model_name 指定要使用的模型

  • -—quantize 标志控制是否应量化模型

  • -—delegate 标志控制我们是否尝试将图的一部分降低到 XNNPACK 委托。

生成的模型文件将被命名为 [model_name]_xnnpack_[qs8/fp32].pte,具体取决于提供的参数。

使用 CMake 运行 XNNPACK 模型

导出 XNNPACK 委托模型后,我们现在可以尝试使用 CMake 和示例输入运行它。我们可以构建和使用 xnn_executor_runner,它是 ExecuTorch 运行时和 XNNPACK 后端的示例包装器。我们首先开始配置 CMake 构建,如下所示

# cd to the root of executorch repo
cd executorch

# Get a clean cmake-out directory
./install_requirements.sh --clean
mkdir cmake-out

# Configure cmake
cmake \
    -DCMAKE_INSTALL_PREFIX=cmake-out \
    -DCMAKE_BUILD_TYPE=Release \
    -DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
    -DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
    -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
    -DEXECUTORCH_BUILD_XNNPACK=ON \
    -DEXECUTORCH_ENABLE_LOGGING=ON \
    -DPYTHON_EXECUTABLE=python \
    -Bcmake-out .

然后,您可以使用以下命令构建运行时组件

cmake --build cmake-out -j9 --target install --config Release

现在您应该能够在 ./cmake-out/backends/xnnpack/xnn_executor_runner 找到构建的可执行文件,您可以使用您生成的模型运行该可执行文件,如下所示

./cmake-out/backends/xnnpack/xnn_executor_runner --model_path=./mv2_xnnpack_fp32.pte
# or to run the quantized variant
./cmake-out/backends/xnnpack/xnn_executor_runner --model_path=./mv2_xnnpack_q8.pte

使用 XNNPACK 后端构建和链接

您可以构建 XNNPACK 后端 CMake 目标,并将其与您的应用程序二进制文件(例如 Android 或 iOS 应用程序)链接。有关此方面的更多信息,您可以查看下一个 资源

文档

访问 PyTorch 的全面开发者文档

查看文档

教程

获取面向初学者和高级开发者的深入教程

查看教程

资源

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

查看资源