目录

ExecuTorch 运行时概述

本文档讨论了 ExecuTorch 运行时的设计,该运行时执行 ExecuTorch 程序文件在边缘设备(如智能手机、可穿戴设备)和 嵌入式设备。主执行 API 的代码位于 下

在阅读本文档之前,我们建议您阅读 ExecuTorch 如何 有效

在最高级别,ExecuTorch 运行时负责:

  • 加载由 模型降低过程。.pte

  • 执行实现 lowered model 的一系列指令。

请注意,截至 2023 年底,ExecuTorch 运行时仅支持模型推理, 并且尚不支持 training。

此图显示了高级流程和涉及的组件: 导出并执行 ExecuTorch 程序:

ExecuTorchRuntime 的高级图

运行时还负责:

  • 管理加载和执行期间使用的内存,可能跨 多个内存库,如 SRAM 和 DRAM。

  • 将符号运算符名称(如)映射到具体 C++ 实现 这些运算符的语义。"aten::add.out"

  • 将模型的预定部分分派到后端 delegates 进行加速。

  • (可选)在加载期间收集分析数据,以及 执行。

设计目标

ExecuTorch 运行时旨在在各种边缘设备上运行, 从现代智能手机 CPU 到资源受限的微控制器和 DSP。 它对将执行委托给一个或多个 backends 以利用特定于架构的优化和现代 异构架构。它体积小且便于携带,可以直接在 没有操作系统、动态内存的裸机嵌入式环境,或者 线程。

低执行开销

记忆

  • 核心运行时库在构建时没有内核或 backends 的

  • 常量张量直接指向文件数据,避免复制 那个数据。这些数据块的对齐方式可以在创建时进行调整。.pte.pte

  • 后端委托可以选择在建模后卸载其预编译的数据 初始化,从而减少峰值内存使用量。

  • 可变张量内存布局是提前规划的,并打包到一个小型的 一组用户分配的缓冲区,提供对内存的精细控制 位置。这在具有异构内存的系统上特别有用 层次结构,允许放置在靠近内核的 SRAM 或 DRAM 上 将对数据进行操作。

中央处理器

  • 模型执行是指令数组的简单循环,其中大部分指令 是指向内核和后端委托的函数指针。这将使 执行开销很小,大约为微秒到纳秒 操作。

  • 操作(如 “add” 或 “conv3d”) 的实现可以完全 针对特定目标系统进行自定义,而无需修改 原始模型或生成的文件。.pte

熟悉的 PyTorch 语义

ExecuTorch 是 PyTorch 堆栈的一类组件,它重用了 API 和 语义。

  • ExecuTorch 使用的 C++ 类型与相应的 类型,以及 ExecuTorch 用于在两者之间进行转换。这对于已经使用 PyTorch C++ 类型。c10::at::

  • 运算符 like 和 的语义相同 在 ExecuTorch 和核心 PyTorch 之间。ExecuTorch 提供了一个测试框架 来确保这一点,并帮助测试这些 Operator 的未来实现。aten::addaten::sigmoid

可移植代码和架构

ExecuTorch 运行时在实现时考虑了可移植性,因此用户 可以为各种目标系统构建它。

C++ 语言注意事项

  • 该代码与 C++17 兼容,可与较旧的工具链一起使用。

  • 运行时不使用异常或 RTTI,尽管它不是对抗性的 对他们来说。

  • 该代码与 GCC 和 Clang 兼容,并且还使用 几个专有的嵌入式工具链。

  • 该存储库提供了 CMake 构建系统,使集成更容易。

操作系统注意事项

运行时不进行直接系统调用。对内存、文件、日志记录、 时钟通过 Runtime Platform Abstraction Layer 抽象出来 (PAL)和注入的接口(如 和 )。请参阅 运行时 API 参考 以了解更多信息。DataLoaderMemoryAllocator

应用程序可以通过 、 、 和 类 控制所有内存分配。核心 运行时不会直接调用 OR ,也不会直接调用类似于 ALLOCATE 在后台分配的类型。这使得:MemoryManagerMemoryAllocatorHierarchicalAllocatorDataLoadermalloc()newstd::vector

  • 在没有堆的环境中运行,但如果需要,仍使用堆。

  • 避免在模型加载和执行期间在堆上同步。

  • 控制用于不同类型数据的内存区域。例如 一组可变张量可以位于 SRAM 中,而另一组位于 DRAM 中。

  • 轻松监控运行时使用的内存量。

但是,请注意,特定的内核或后端实现可能会使用 任意运行时或操作系统功能。用户应仔细检查 docs 来获取它们使用的内核和后端库。

线程处理注意事项

核心运行时不进行线程处理或锁定,也不使用线程本地 变量。但是,它与更高级别的同步配合得很好。

  • 每个实例都是不可变的,因此是完全的 线程安全。 多个线程可以同时访问单个实例。ProgramProgram

  • 每个实例都是可变的,但自包含,因此是有条件的 线程安全。 多个线程可以并发访问和执行独立的实例,但单个实例的访问和执行必须序列化。MethodMethod

但是,请注意:

  • 在 : 期间可以读取两个全局表 内核注册表和后端注册表。Program::load_method()

    • 实际上,这些表仅在进程/系统加载时修改。 并在加载第一个之前被有效地冻结。但是一些 应用程序可能需要了解这些表,尤其是当它们 在 process/system load time 后手动更改它们。Program

  • 特定的内核或后端实现可能有自己的线程 限制。用户应仔细检查内核和后端的文档 他们使用的库。

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

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

查看教程

资源

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

查看资源