• 文档 >
  • 使用 ARM Ethos-U 后端构建和运行 ExecuTorch
快捷方式

使用 ARM Ethos-U 后端构建和运行 ExecuTorch

我们建议你在本教程之前完成的教程
在本教程中你将学到什么

在本教程中,你将学习如何导出用于 ExecuTorch Arm Ethos-u 后端委托的简单 PyTorch 模型,并在 Corstone-300 FVP 模拟器上运行它。

警告

此 ExecuTorch 后端委托正在积极开发中。你可能会遇到一些可能已记录或已规划但尚未实现的粗糙部分和功能。

提示

如果你已经熟悉此委托,则可能需要直接跳转到示例源目录 - https://github.com/pytorch/executorch/tree/main/examples/arm

前提条件

在开始之前,让我们确保你拥有所需的一切。

硬件

要成功完成本教程,你需要一台基于 Linux 的主机,其 Arm aarch64 或 x86_64 处理器架构。

目标设备将是带有 Arm Cortex-M55 CPU 和 Ethos-U55 NPU(ML 处理器)的嵌入式平台。本教程将向你展示如何在两者上运行 PyTorch 模型。

我们将使用一个固定虚拟平台 (FVP),模拟一个Corstone-300(cs300) 系统。由于我们将使用 FVP(可以将其视为虚拟硬件),因此本教程不需要任何真正的嵌入式硬件。

软件

首先,你需要安装 ExecuTorch。如果你还没有安装,请按照推荐的教程进行操作,以设置一个可用的 ExecuTorch 开发环境。

要生成可以在嵌入式平台(真实或虚拟)上运行的软件,我们需要一个用于交叉编译的工具链和一个 Arm Ethos-U 软件开发工具包,其中包括 Vela 编译器(用于 Ethos-U NPU)。

在以下部分中,我们将逐步介绍下载上面列出的每个依赖项。

设置开发环境

在本部分中,我们将进行一次性设置,例如下载和安装必要的软件,以获取本教程中运行 ExecuTorch 程序所需的平台支持文件。有两种可用的方法

  1. 方法 1:使用examples/arm/setup.sh 脚本以自动化方式提取每个项目(推荐)。建议在 conda 环境中运行脚本。执行成功后,你可以直接转到下一步

  2. 方法 2:逐步按照指南进行操作,以了解脚本的所有组件和逻辑。如果你打算大幅更改流程的行为,则可能需要使用此方法。

提示

在 ExecuTorch 存储库中,我们有一个遵循完全相同步骤的运行脚本,以加快速度。它位于examples/arm/setup.sh。如果你方便的话,可以随意使用它,或者在手动说明中的某些步骤不是很清楚时将其用作参考。

如前所述,我们目前仅支持具有 x86_64 或 aarch64 处理器架构的基于 Linux 的平台。让我们确保我们确实在一个受支持的平台上。

uname -s
# Linux

uname -m
# x86_64 or aarch64

让我们创建一个空目录,并将其用作顶级开发目录。

下载并设置 Corstone-300 FVP

固定虚拟平台 (FVP) 是对流行系统配置进行预配置、功能准确的模拟。在本教程中,我们对 Corstone-300 系统感兴趣。我们可以从 Arm 网站下载它。

注意

下载并运行 FVP 软件,即表示您同意 FVP 最终用户许可协议 (EULA)

要下载,我们可以从 此处 下载 Corstone-300 Ecosystem FVP。或者,您可以下载我们测试过的相同版本,如下所示:

# for aarch64
curl \
    --output FVP_cs300.tgz \
    'https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_35_Linux64_armv8l.tgz?rev=b083dc5ac9c546899fbb7ccd67b74c17&hash=BFE589289ECF12B07192636382C15C01'

# for x86_64
curl \
    --output FVP_cs300.tgz \
    'https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_20_Linux64.tgz?rev=018659bd574f4e7b95fa647e7836ccf4&hash=22A79103C6FA5FFA7AFF3BE0447F3FF9'

现在,在新的目录中解压 FVP_cs300.tgz 文件,并运行提供的脚本,该脚本将安装 FVP。

./FVP_Corstone_SSE-300.sh          \
   --i-agree-to-the-contained-eula \
   --force                         \
   --destination ./                \
   --quiet                         \
   --no-interactive

成功后,让我们确保 FVP 模拟器在 PATH 中可用,以便以后使用。

# for x86-64 hosts
export PATH=${PATH}:<install_dir>/FVP/models/Linux64_GCC-9.3
# for aarch64 hosts
export PATH=${PATH}:<install_dir>/FVP/models/Linux64_armv8l_GCC-9.3/

hash FVP_Corstone_SSE-300_Ethos-U55 # To make sure we are ready to use

下载并安装 Arm GNU AArch32 裸机工具链

与 FVP 类似,我们还需要一个工具链来交叉编译 ExecuTorch 运行时、executor-runner 裸机应用程序以及 Corstone-300 平台上可用的 Cortex-M55 CPU 的其余裸机堆栈。

这些工具链可在此处获得 此处。对于本教程,我们将使用针对 arm-none-eabi 的 GCC 12.3。与 FVP 一样,要下载我们顶级开发目录中测试过的相同版本,

# for aarch64
curl \
    --output gcc.tar.xz \
    'https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-aarch64-arm-none-eabi.tar.xz'

# for x86_64
curl \
    --output gcc.tar.xz \
    'https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz'

下载后,您可以在新目录中解压其内容。然后,让我们确保工具链在 PATH 中可用,以便以后使用。

export PATH=${PATH}:/<install_dir>/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin
export PATH=${PATH}:/<install_dir>/arm-gnu-toolchain-12.3.rel1-aarch64-arm-none-eabi/bin

hash arm-none-eabi-gcc # To make sure we are ready to use

设置 Arm Ethos-U 软件开发

此 git 存储库是所有 Arm Ethos-U 软件的根目录。它可以帮助我们下载所需的存储库并将它们放在树形结构中。在顶级开发目录中,

# Download the repo
git clone https://review.mlplatform.org/ml/ethos-u/ethos-u
cd ethos-u

# To align with the version we have tested
git reset --hard 0995223100e3da8011700f58e491f1bf59511e3c

# Download the necessary repos and properly install them
./fetch_externals.py fetch

# Download the Vela compiler
cd .. # To the top-level development dir
git clone https://review.mlplatform.org/ml/ethos-u/ethos-u-vela

完成后,您应该拥有一个可用的 FVP 模拟器、一个用于交叉编译的功能工具链以及为裸机开发做好准备的 Ethos-U 软件开发设置。

应用本地补丁

由于此功能正在积极开发中,我们有一些针对 Arm Ethos-u 软件开发工具包的补丁。让我们将它们应用于下载的 SDK 和 Vela 编译器。

cd ethos-u # this is the top level Ethos-U software directory

# Let's patch core_platform repo
cd core_platform
git reset --hard 204210b1074071532627da9dc69950d058a809f4
git am -3 <path_to>/executorch/examples/arm/ethos-u-setup/core_platform/patches/*.patch
cd ../.. # To the top-level development dir

安装 Vela 编译器

修补完成后,让我们通过安装 Vela 编译器完成设置。

cd ethos-u-vela
pip install .

安装 TOSA 参考模型

git clone https://review.mlplatform.org/tosa/reference_model -b v0.80
cd reference_model
git submodule update --init --recursive
mkdir -p build
cd build
cmake ..
n=$(nproc)
make -j"$((n - 5))"
cd reference_model # Within the build directory
# Add tosa_reference_model to the path
export PATH=${PATH}:`pwd`

在设置结束时,如果一切顺利,你的顶级开发目录可能如下所示,

.
├── arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi # for x86-64 hosts
├── ethos-u
│   ├── core_platform
│   ├── core_software
│   ├── fetch_externals.py
│   └── [...]
├── ethos-u-vela
├── FVP
│   ├── FVP_Corstone_SSE-300.sh
│   └── [...]
├── FVP_cs300.tgz
├── gcc.tar.xz
└── reference_model

将 PyTorch 模型转换为 .pte 文件

.pte 是 ExecuTorch 预先 (AoT) 管道通过获取 PyTorch 模型 (torch.nn.Module),导出它,运行各种传递,最后将其序列化为 .pte 文件格式而产生的二进制文件。此二进制文件通常由 ExecuTorch 运行时使用。此 文档更深入地介绍了 ExecuTorch 软件堆栈,包括 AoT 和运行时。

在本节中,我们将主要关注 AoT 流程,最终目标是生成 .pte 文件。有一组导出配置以在运行时针对不同的后端。对于每个配置,AoT 流程将生成一个唯一的 .pte 文件。我们将探索生成不同 .pte 文件的不同配置,这对于我们的 Corstone-300 系统和可用的处理元素特别有趣。

在开始之前,让我们首先讨论我们将使用的 PyTorch 模块。

PyTorch 示例模块

我们将使用几个简单的 PyTorch 模块来探索端到端流程。这些模块将在整个教程中以各种不同的方式使用,通过其 <class_name> 引用它们。

SoftmaxModule

这是一个非常简单的 PyTorch 模块,只有一个 Softmax 算子。

import torch

class SoftmaxModule(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.softmax = torch.nn.Softmax()

    def forward(self, x):
        z = self.softmax(x)
        return z

使用 Python 环境(在同一开发 Linux 机器上)运行它,我们得到了预期的输出。

>>> m = SoftmaxModule()
>>> m(torch.ones(2,2))
tensor([[0.5000, 0.5000],
        [0.5000, 0.5000]])

AddModule

让我们用一个 Add 运算符编写另一个简单的 PyTorch 模块。

class AddModule(torch.nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        return x + x

使用 Python 环境(在同一开发 Linux 机器上)运行它,正如预期的那样,1 + 1 确实产生 2。

>>> m = AddModule()
>>> m(torch.ones(5, dtype=torch.int32)) # integer types for non-quantized Ethos-U delegation
tensor([2, 2, 2, 2, 2], dtype=torch.int32)

记住这些模块的输入和输出。当我们通过其他方式降低并运行它而不是在该 Linux 机器上运行时,我们将使用相同的输入,并期望输出与此处显示的输出匹配。

提示

我们需要了解在 Ethos-U55 上运行网络的数据类型,因为它仅是一个整数处理器。对于此示例,我们显式使用整数类型,对于此类流程的典型用法,网络以浮点构建和训练,然后从浮点量化为整数以进行高效推理。

非委托工作流

在 ExecuTorch AoT 管道中,其中一个选项是选择后端。ExecuTorch 提供了各种不同的后端。选择后端是可选的,通常是为了针对给定模型计算要求的特定加速或硬件模式。如果没有后端,ExecuTorch 运行时将回退到使用默认情况下可用的高度可移植的运算符集。

预计在具有专用加速功能的平台(如 Ethos-U55)上,非委托流程用于两种主要情况

  1. 当网络设计得非常小,最适合单独在 Cortex-M 上运行时。

  2. 当网络具有可以针对 NPU 的操作和无法针对 NPU 的操作的混合时,例如 Ethos-U55 支持整数操作,因此浮点 softmax 将回退到 CPU 上执行。

在此流程中,在不使用任何后端委托的情况下,为了说明 ExecuTorch 运行时的可移植性以及运算符库的可移植性,我们将在 .pte 生成期间跳过指定后端。

以下脚本将作为帮助实用程序,帮助我们生成 .pte 文件。它在 examples/arm 目录中提供。

python3 -m examples.arm.aot_arm_compiler --model_name="softmax"
# This should produce ./softmax.pte

委托工作流

与 Arm 合作,我们为 ExecuTorch 引入了新的 Arm 后端委托。此后端正在积极开发中,并且在撰写本文时具有有限的功能集。

通过在 ExecuTorch AoT 导出管道中包含以下步骤来生成 .pte 文件,我们可以启用此后端委托。

from executorch.backends.arm.arm_backend import generate_ethosu_compile_spec

graph_module_edge.exported_program = to_backend(
    model.exported_program,
    ArmPartitioner(generate_ethosu_compile_spec("ethos-u55-128")))

与非委托流程类似,同一个脚本将作为帮助实用程序,帮助我们生成 .pte 文件。注意 --delegate 选项以启用 to_backend 调用。

python3 -m examples.arm.aot_arm_compiler --model_name="add" --delegate
# should produce ./add_arm_delegate.pte

在此结束时,我们应该有两个不同的 .pte 文件。第一个带有 SoftmaxModule,没有任何后端委托。第二个带有 AddModule,并启用了 Arm Ethos-U 后端委托。现在,让我们尝试在裸机环境中的 Corstone-300 平台上运行这些 .pte 文件。

获取裸机可执行文件

在本节中,我们将介绍构建运行时应用程序所需执行的步骤。然后在目标设备上运行。

提示

在 executorch 存储库中,我们有一个执行完全相同步骤的功能脚本。它位于 executorch/examples/arm/run.sh。如果您方便,可以随意使用它,或者如果手动说明中的一些步骤不是很清楚,可以使用它作为参考。

此外,在开始之前,请确保您已完成 ExecuTorch cmake 构建设置,以及 前面描述的设置开发环境的说明。

下图演示了各种构建工件如何生成并在高级别上链接在一起以生成最终裸机可执行文件。

生成 ExecuTorch 库

ExecuTorch 的 CMake 构建系统生成了一组构建部分,这些部分对于我们包含和在 Ethos-U SDK 提供的 Corstone-300 的裸机环境中运行 ExecuTorch 运行时至关重要。

文档提供了每个单独构建部分的详细概述。对于运行 .pte 文件的任一变体,我们需要一组核心库。以下是列表,

  • libexecutorch.a

  • libportable_kernels.a

  • libportable_ops_lib.a

要使用 Arm 后端委托调用指令运行 .pte 文件,我们需要 Arm 后端委托运行时库,即,

  • libexecutorch_delegate_ethos_u.a

要生成这些库,请使用以下命令,

# Empty and already created
cd <executorch_source_root_dir>

# Use provided cmake toolchain for bare-metal builds
toolchain_cmake=<executorch_source_root_dir>/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake

cmake                                                 \
    -DBUCK2=${buck2}                                  \
    -DCMAKE_INSTALL_PREFIX=<executorch_build_dir>     \
    -DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF            \
    -DCMAKE_BUILD_TYPE=Release                        \
    -DEXECUTORCH_ENABLE_LOGGING=ON                    \
    -DEXECUTORCH_BUILD_ARM_BAREMETAL=ON               \
    -DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON       \
    -DFLATC_EXECUTABLE="$(which flatc)"               \
    -DCMAKE_TOOLCHAIN_FILE="${toolchain_cmake}"       \
    -B<executorch_build_dir>                          \
    <executorch_source_root_dir>

cmake --build <executorch_build_dir> --target install --config Release

cmake                                                 \
    -DCMAKE_INSTALL_PREFIX=<executorch_build_dir>     \
    -DCMAKE_BUILD_TYPE=Release                        \
    -DEXECUTORCH_SELECT_OPS_LIST="aten::_softmax.out" \
    -DCMAKE_TOOLCHAIN_FILE="${toolchain_cmake}"       \
    -B<executorch_build_dir>/examples/arm             \
    <executorch_source_root_dir>/examples/arm

cmake --build <executorch_build_dir>/examples/arm --config Release

EXECUTORCH_SELECT_OPS_LIST 将决定构建中包含的便携式运算符的数量,并且在运行时可用。它必须与 .pte 文件的要求相匹配,否则您将在运行时收到 Missing Operator 错误。

例如,在上面的命令行中,要运行 SoftmaxModule,我们只包括了 softmax CPU 运算符。类似地,要在非委托方式中运行 AddModule,您将需要添加运算符,依此类推。您可能已经意识到,对于将由 Arm 后端委托执行的委托运算符,我们不需要将这些运算符包含在此列表中。这仅适用于非委托运算符。

构建 executor_runner 裸机应用程序

SDK 目录与之前准备的相同。并且,我们将传递上面生成的 .pte 文件(其中任何一个)。

请注意,如果您要更改模型或 .pte 文件,则必须生成新的 executor-runner 二进制文件。此约束来自我们为 Corstone-300 平台提供的受限裸机运行时环境。

cd <executorch_source_root_dir>
cd examples/arm/executor_runner

cmake                                                    \
    -DCMAKE_TOOLCHAIN_FILE="${toolchain_cmake}"          \
    -DTARGET_CPU=cortex-m55                              \
    -B build                                             \
    -DETHOS_SDK_PATH:PATH=<ethos-u_clone_directory>      \
    -DET_DIR_PATH:PATH=<executorch_source_root_dir>      \
    -DET_BUILD_DIR_PATH:PATH=<executorch_build_dir>      \
    -DET_PTE_FILE_PATH:PATH=<path_to_pte_file_of_choice> \
    -DPYTHON_EXECUTABLE=$(which python3)

cmake --build build -- arm_executor_runner

在 Corstone-300 FVP 平台上运行

一旦准备好 elf,无论使用哪个 .pte 文件变体来生成裸机 elf,您都可以使用以下命令运行,

ethos_u_build_dir=examples/arm/executor_runner/

elf=$(find ${ethos_u_build_dir} -name "arm_executor_runner")

FVP_Corstone_SSE-300_Ethos-U55                          \
    -C ethosu.num_macs=128                              \
    -C mps3_board.visualisation.disable-visualisation=1 \
    -C mps3_board.telnetterminal0.start_telnet=0        \
    -C mps3_board.uart0.out_file='-'                    \
    -a "${elf}"                                         \
    --timelimit 10 # seconds - after which sim will kill itself

如果成功,模拟器应在 shell 上生成类似以下内容,

    Ethos-U rev 136b7d75 --- Apr 12 2023 13:44:01
    (C) COPYRIGHT 2019-2023 Arm Limited
    ALL RIGHTS RESERVED

I executorch:runner.cpp:64] Model PTE file loaded. Size: 960 bytes.
I executorch:runner.cpp:70] Model buffer loaded, has 1 methods
I executorch:runner.cpp:78] Running method forward
I executorch:runner.cpp:95] Setting up planned buffer 0, size 32.
I executorch:runner.cpp:110] Method loaded.
I executorch:runner.cpp:112] Preparing inputs...
I executorch:runner.cpp:114] Input prepared.
I executorch:runner.cpp:116] Starting the model execution...
I executorch:runner.cpp:121] Model executed successfully.
I executorch:runner.cpp:125] 1 outputs:
Output[0][0]: 0.500000
Output[0][1]: 0.500000
Output[0][2]: 0.500000
Output[0][3]: 0.500000
Application exit code: 0.

EXITTHESIM

Info: Simulation is stopping. Reason: CPU time has been exceeded.

在此示例中,我们使用为 SoftmaxModule 生成的 softmax.pte 文件运行了 executor_runner 二进制文件,我们确实看到了在 FVP 模拟器上运行的 Corstone-300 虚拟硬件上生成的裸机二进制文件产生的预期结果。

如果您使用 AddModule 的委托 .pte 文件重新运行相同的 FVP 命令,即 add_arm_delegate.pte - 您可能会得到类似以下内容,同样是预期结果。注意带有前缀 ArmBackend:: 打印的消息,它们表明后端已成功初始化,并且 .pte 中 AddModule 中的 add 运算符在 Ethos-U55 NPU 上执行。

    Ethos-U rev 136b7d75 --- Apr 12 2023 13:44:01
    (C) COPYRIGHT 2019-2023 Arm Limited
    ALL RIGHTS RESERVED

I executorch:runner.cpp:64] Model PTE file loaded. Size: 2208 bytes.
I executorch:runner.cpp:70] Model buffer loaded, has 1 methods
I executorch:runner.cpp:78] Running method forward
I executorch:runner.cpp:95] Setting up planned buffer 0, size 64.
I executorch:ArmBackendEthosU.cpp:51] ArmBackend::init 0x11000050
I executorch:runner.cpp:110] Method loaded.
I executorch:runner.cpp:112] Preparing inputs...
I executorch:runner.cpp:114] Input prepared.
I executorch:runner.cpp:116] Starting the model execution...
I executorch:ArmBackendEthosU.cpp:103] ArmBackend::execute 0x11000050
I executorch:runner.cpp:121] Model executed successfully.
I executorch:runner.cpp:125] 1 outputs:
Output[0][0]: 2
Output[0][1]: 2
Output[0][2]: 2
Output[0][3]: 2
Output[0][4]: 2
Application exit code: 0.

EXITTHESIM

Info: Simulation is stopping. Reason: CPU time has been exceeded.

要点

通过本教程,我们了解了如何使用 ExecuTorch 软件从 PyTorch 导出标准模型,并在紧凑且功能齐全的 ExecuTorch 运行时上运行它,为将模型从 PyTorch 卸载到基于 Arm 的平台开辟了一条平滑的道路。

回顾一下,有两个主要流程

  • 使用内置于 ExecuTorch 中的库将工作卸载到 Cortex-M 的直接流程。

  • 将图形划分为 Cortex-M 部分和可以在 Ethos-U 硬件上卸载和加速的部分的委托流程。

这两个流程都在不断发展,支持更多用例并提高性能。

常见问题解答

如果您在按照本教程操作时遇到任何错误或问题,请在此处提交错误/问题Github

文档

访问 PyTorch 的综合开发者文档

查看文档

教程

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

查看教程

资源

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

查看资源