目录

使用 XNNPACK 后端构建和运行 ExecuTorch

以下教程将让您熟悉如何利用 ExecuTorch XNNPACK Delegate 通过 CPU 硬件加速 ML 模型。它将介绍如何将模型导出和序列化为二进制文件,以 XNNPACK Delegate Backend 为目标,并在支持的目标平台上运行模型。要快速入门,请使用 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()],
)

我们将使用从 TorchVision 库下载的 MobileNetV2 预训练模型来介绍此示例。降低模型的流程在导出模型后开始。我们使用 .分区程序标识适合 XNNPACK 后端委托使用的子图。之后,将使用 XNNPACK Delegate flatbuffer 模式对标识的子图进行序列化,并且每个子图都将替换为对 XNNPACK Delegate 的调用。to_edgeto_backendXnnpackPartitioner

>>> 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 的子图是每个调用站点的第一个参数。可以观察到,大多数块和块都能够委托给 XNNPACK。我们还可以看到无法降低到 XNNPACK 委托的运算符,例如 和 。convolution-relu-addlinearcloneview_copy

exec_prog = edge.to_executorch()

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

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

将量化模型降低到 XNNPACK

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

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)

量化需要两个阶段的导出。首先,我们使用 API 捕获模型,然后再将其提供给 utility function。执行量化步骤后,我们现在可以利用 XNNPACK 委托来降低量化导出的模型图。从这里开始,该过程与将非量化模型降低到 XNNPACK 的过程相同。export_for_trainingquantize

# 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

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

生成的模型文件将根据提供的参数进行命名。[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
rm -rf cmake-out
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 的全面开发人员文档

查看文档

教程

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

查看教程

资源

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

查看资源