本页提供了 Portable Kernel Library 和 Optimized Kernel Library 的描述,它们是 ExecuTorch 附带的默认内核库。建议那些对使用这些内核库执行 ExecuTorch 程序的人,或者那些想要实现自己的内核和内核库的人阅读。
ExecuTorch 的内核库概述¶
ExecuTorch 程序对描述程序应执行的计算的指令进行编码。其中许多指令对应于调用特定的 ATen 运算符,例如 .但是,ExecuTorch 的核心设计原则之一是 operator 的签名应该与 operator 的实现分开。这意味着 ExecuTorch 运行时不附带 ATen 运算符的任何标准实现;用户必须确保链接到包含其 ExecuTorch 程序所需运算符实现的内核库,并配置 Operator 注册以将 Operator 签名映射到所需的实现。这使得调整运算符的实现变得容易,例如在执行 ExecuTorch 程序时将调用的运算符;它允许用户选择确切的 Operator 实现,以满足其用例的独特性能、内存使用、电池使用等约束。aten.convolution
aten.convolution
从本质上讲,内核库只是遵循共同主题或设计原则的 ATen 运算符实现的集合。请注意,由于 ExecuTorch 的选择性构建过程(将在下一节中讨论),运算符实现是单独链接的。这意味着用户可以轻松地在他们的构建中混合不同的内核库,而不会牺牲构建大小。
ExecuTorch 默认附带两个内核库:Portable Kernel Library 和 Optimized Kernel Library,两者都提供 CPU 算子实现。
可移植内核库¶
从某种意义上说,可移植内核库是 ExecuTorch 使用的 “参考” 内核库。Portable Kernel Library 的开发考虑了以下目标:
正确性
提供 ATen 算子的直接实现,与 PyTorch 的 ATen 库中算子的原始实现严格一致
可读性 / 简单性
提供清晰、可读的源代码,以便想要开发 Operator 的自定义实现的人可以轻松理解 Operator 的所需行为。
可移植性
可移植内核应该与 ExecuTorch 运行时一样可移植;运算符实现不应使用任何外部依赖项,也不应使用任何未经批准的 C++ 功能。
运维覆盖范围
作为 ExecuTorch 的 “参考” 内核库,Portable Kernel Library 旨在具有高度的算子覆盖率。目标是让 Portable Kernel 库为列为 Core ATen 运算符的每个运算符提供一个实现。但是,请注意,Portable Kernel Library 的 operator 覆盖率仍在进行中。
Portable Kernel Library 的主要目的是提供易于访问的 operator 实现,这些 Implementations 将在大多数平台上 “正常工作”,并保证提供正确的输出。性能不是 Portable Kernel Library 的目标。事实上,许多瓶颈运算符(如卷积和矩阵乘法)都是以最直接的方式实现的,以优先考虑简单性和可读性。因此,如果仅使用 Portable Kernel 库,则不应期望观察到快速推理时间。但是,除了特定的瓶颈运算符之外,大多数运算符都足够简单,其中 Portable Kernel Library 的直接实现仍应提供足够的性能。二进制大小也是 Portable Kernel Library 的非目标。
优化的内核库¶
优化内核库是 ExecuTorch 附带的补充内核库,与可移植内核库相比,它旨在以牺牲可移植性和可读性为代价,提供以性能为中心的运算符实现。Optimized Kernel Library 中的许多 operator 实现都受到 PyTorch 的 ATen 库中相应实现的启发或基于,因此在许多情况下,可以预期相同程度的性能。
一般来说,Optimized Kernel Library 中的算子通过以下两种方式之一进行优化:
使用 CPU 向量内部函数
使用优化的数学库,例如 和
sleef
OpenBLAS
尽管可移植性不是 Optimized Kernel Library 的设计目标,但实现并不意味着要针对特定的 CPU 架构进行微调。相反,Optimized Kernel 库寻求提供可应用于各种平台的高性能实现,而不是使用特定于单个平台的优化。
另一个重要的注意事项是,算子覆盖率也不是 Optimized Kernel Library 的目标。没有计划为每个 Core ATen 运算符添加优化的内核;相反,会根据需要添加优化的内核,以提高特定模型的性能。因此,与 Portable Kernel Library 相比,Optimized Kernel Library 中的算子覆盖率将受到更多限制。