RFC-0151:针对 CPU 目标的编译器调整标志

RFC-0151:用于 CPU 定位的编译器调整标志
状态已接受
领域
  • 工具链
说明

提议对编译器标志进行更改,以控制 CPU 定位,以及这些标志对平台和 SDK build 的影响。

问题
  • 90784
Gerrit 更改
  • 624521
作者
审核人
提交日期(年-月-日)2022-01-04
审核日期(年-月-日)2022-02-02

总结

提议对编译器标志进行更改,以管理 CPU 定位及其对平台和 SDK build 的影响。

设计初衷

Fuchsia 的 build 会生成许多工件,这些工件包含不同架构的可执行机器代码。例如:发布以供 SDK 使用的预构建共享库,或平台和产品系统映像中包含的可执行 C/C++ 或 Rust 二进制文件。在编译器中生成机器代码时,请务必指明以下内容:

目标架构:要使用的指令集架构?例如 x86-64 或 AArch64 ISA。此外,编译器可能会定位 ISA 的修订版本。 修订版本可能会提供可显著提升性能的额外指令或变体,例如新的浮点或 SIMD 指令,或更广泛的原子内存操作。了解目标架构以生成保证可在目标设备上运行的代码至关重要。“提升”目标架构以与旧硬件向后兼容为代价解锁新功能。

ARM ISA 的发展

上图:ARM ISA 的进展(来源

目标微架构:如何实现 ISA?这通常表现为指令是按顺序执行还是无序执行、解码带宽、缓存加载延迟时间等。通过指定目标微架构,编译器可以生成可在目标硬件上更快运行的机器代码,而不会限制硬件兼容性。

Intel Core 2 微架构

上图:Intel Core 2 微架构方框图(来源

编译器允许用户以我们稍后将会介绍的方式指定这些目标。Fuchsia 的构建系统能够全局或每个二进制文件配置编译器。Fuchsia 的 build 中现有的 CPU 定位实现存在一些缺点,此 RFC 旨在解决这些缺点:

  1. 选择 arm64 基准配置后,系统会针对特定 CPU (Cortex-A53),而非使用 ISA+ 功能。这会导致定义不明确的平台基准。

  2. 由于缺乏现有技术并且没有载明的政策或最佳实践,因此尚不清楚如何设置此基准的替换项。因此,Fucsia 会构建所有不同版本但回退到基准测试的版本,包括明确针对基准之外的硬件的 build 配置。

自 2016 年 build 推出以来,一直存在这些缺点,在此之前,Fuchsia 从其前述技术中得到了改进。当前的系统在第一台设备上搭载了 Fuchsia(该设备恰好使用与当今平台 arm64 基准相同的微架构)。

最新发展表明,是时候进行全面改革了。具体而言,除了针对 Cortex-A53 的 Astro 和 Sherlock 开发板配置之外,Fuchsia 现在还支持 Nelson 开发板配置 (Cortex-A55) 和 Atlas 开发板配置 (Intel Amber Lake)。不过,这些 build 当前未配置为利用基准与实际目标之间的差异。

此外,优化平台硬件基准定义或提高该基准定义越来越受关注。更清晰地定义基准配置和具体板级配置可以加快相关工作的速度。另请参见:

为了应对当前和未来的挑战,此 RFC 提议立即对 build 中的 CPU 定位做出变更,以及在可预见的未来对定位进行治理的机制和政策。

利益相关方

教员cpu@google.com

审核者

  • aaronwood@google.com - 系统组装
  • digit@google.com - build
  • mcgrathr@google.com - 内核
  • mvanotti@google.com - 安全
  • maniscalco@google.com - 内核
  • phosek@google.com - 工具链
  • travisg@google.com - 内核

咨询人员

由于建议的更改会影响平台的大部分内容,因此建议各方根据咨询内容自行指定。特别欢迎图形、媒体和 SDK 等团队提供反馈

社交

我们首先在 Fuchsia 的内核演变工作组以 60 分钟的时间演示和公开讨论的形式对该方案进行了审阅。

背景

编译时调整标志

Fuchsia 使用 Clang 编译 C/C++,并且一些 Fuchsia 代码子集也在使用 gcc 持续构建和测试。这两种工具都提供以下标志:

-march:设置目标架构,例如 x86-64-v2(我们根据 RFC-0073 提供的当前 x64 基准)或 ARMv8-A。还可以指定其他架构功能,例如,+avx2 以指明高于 x64 基准的 Intel Haswell 扩展。

-mtune:设置目标微架构,例如 cortex-a53haswell。如果 -mtune-mcpu 均未使用,则此值会设置为 generic,以便在一系列目标 CPU 之间实现平衡。

-mcpu:设置目标 CPU。接受的值与 -mtune 类似。对于 ARM CPU,这相当于设置目标架构 (-march) 和目标微架构 (-mtune) 以匹配目标 CPU。在 x86 上,此函数被视为已废弃,并且指定的值会被重定向到 -mtune

Rust 编译器提供了 codegen 选项,如下所示:

target-cpu:与 -mcpu 类似,例如 cortex-a53

target-features:与 -march 功能类似,例如 +avx2

当前状态

目前,所有 x64 build 都是使用 -march=x86-64-v2 编译的,所有 ARM build 都是使用 -mcpu=cortex-a53 编译的。

有一种通过名为 board_configs 的 GN 参数替换此配置的机制,该机制可被 .gni 文件中的板级配置替换。某些开发板(尤其是 Astro 和 Sherlock)会手动指定上述 Cortex-A53 配置,不过目前这只是空操作,因为在未定义替换项的情况下,相同的配置也可以用作后备配置。大多数板级配置都未设置 board_configs

调整目标和权衡

本部分将简要介绍设置 CPU 定位选项时要考虑的不同目标,以及它们之间的一些权衡。

硬件兼容性:以 ISA 的早期修订版本为目标平台可解锁与旧硬件的兼容性。如果想要实现更好的兼容性,您便无法再使用可在性能或安全性方面带来优势的新 ISA 功能。

性能:新的指令可以带来性能提升:更快或更广泛的原子运算、加速数学(FPU、SIMD 改进),以及针对常用算法(如 CRC 和 AES)的内置加速器。针对指定 CPU 调整机器代码可以生成在目标 CPU 上运行速度更快的代码,但这往往会降低其他 CPU 在目标参数范围之外的性能。

与二进制文件大小的相互作用:据观察,在某些情况下,通过调整来增加二进制文件大小,例如,针对有序处理器的指令调度优化会增加寄存器压力时。

二进制文件大小:某些 Codegen 功能可以通过特定 CPU 功能解锁。例如,SIMD 可启用自动矢量化,其效果与循环展开类似,因为它会生成速度更快但更大的代码。针对有序 CPU 微调的指令调度往往会生成更大的代码,因为它会增加更多的调度约束,并可能增加寄存器压力和寄存器溢出。

其他代码生成功能可能会缩减二进制文件的大小。例如,将 CRC 和 AES 等算法替换为专用指令,从而生成速度更快且更小的代码。

简化问题排查,即二进制文件多样性:针对不同的 CPU 进行调整意味着随着时间的推移生成同一逻辑工件的更多二进制变体。例如,内核映像或预构建共享库的多个“变种”,每个变种都针对不同的目标进行了优化。这可能会使问题重现过程更加复杂,或使 Fuchsia 暴露于某些二进制变体中而不出现的其他问题。

关卡竞争字段:除了基准 build 之外,Fuchsia 还可能提供针对特定 CPU 微调的 SDK 预构建版本(系统映像、可再分发的共享库)。这样一来,某些硬件选择相对于其他硬件选择而言就能获得较窄的权限。合理的假设是,创建针对特定 CPU 的 SDK 变种有助于预期未来提供更精细的 SDK 发布渠道。

简单性:以上所有这一切都增加了了解 Fuchsia、在 Fuchsia 上进行开发和维护 Fuchsia 的复杂性。上述权衡用于设置 CPU 定位选项,以便在可行的情况下在面向特定硬件的构建和分发渠道(例如针对特定用户硬件的 OTA 渠道的构建和发布流水线)设置 CPU 定位选项。在撰写本文时,根本没有系统或软件包分发机制能够为不同的目标硬件提供多个二进制文件,以便将正确的二进制文件与正确的设备进行匹配。

提案

您可以在这项变更中看到直接建议的修改。更多说明如下所示。

新增了 arm64 基准硬件目标

arm64 的当前基准定义为以 Cortex-A53 为目标平台,如下所示:

-mcpu=cortex-a53

从技术上来讲,这相当于根据一组精确的 Cortex-A53 功能来表示 -march,并调整 Cortex-A53 的代码生成功能。

-march=<armv8a + Cortex-A53 features>
-mtune=cortex-a53

相反,基准将表示平台实际执行的(因此被假定为基准)的 ARMv8-A ISA 功能,然后针对通用 armv8a CPU 调整代码生成。

-march=armv8-a+simd+crc+crypto
-mtune=generic

-march 的影响实际上是一种空操作,因为移除 Cortex-A53 中支持但未在代码中练习的 -march 功能就是空操作。

-mtune 的影响很小或没有影响,因为通用调整目标会针对典型的有序 ARMv8-A CPU(例如 Cortex-A53)进行优化。

对现有 x64 基准硬件目标的变更

x64 的当前基准为:

-march=x86-64-v2

前面提到的 RFC-0073: 将 x86-64 平台要求提升到 x86-64-v2 中介绍了此主题。

这将更改为下面设置的标志:

-march=x86-64-v2
-mtune=generic

这并非行为变更,因为如前所述,当未指定 -mtune-mcpu 时,-mtune 默认为 generic。不过,添加 -mtune=generic 会使此行为变得明确,并与 arm64 基准的定义一致。

板级配置

板级 .gni 文件(例如在 //boards/ 中找到的文件)中指定的 board_configs 板级参数将继续用于将基准配置替换为板级专用配置。

具体而言,astro.gnisherlock.gni 等使用 Cortex-A53 的板级配置将继续以 Cortex-A53 为目标平台,并将保留当前的 -mcpu=cortex-a53 配置。

从本质上讲,此 RFC 将获取以 Cortex-A53 为目标的现有 arm64 配置,并将其从平台基准提取到提供此类 CPU 的 Astro 和 Sherlock 开发板的板级配置。然后,此 RFC 以 ARM ISA 术语重新定义了平台基准,这些术语泛化到许多硬件选择,而不是单个 ARM CPU。

此外,在 SDK 的未来版本中,可以添加对针对不同架构变体(例如 ARM Cortex-A73 或 Intel AVX 扩展)进行优化的支持。这需要进一步讨论,不在讨论范围之内。

内核配置

board_configs 参数将不再适用于内核映像。原因如下:

  1. 代码生成时需要知道的较新指令或其他 CPU 功能目前不会给内核带来好处。

  2. 基于微架构的内核代码调整并不能降低因增加二进制文件多样性和复杂性而产生的开销。

内核可以继续提供有关受支持硬件功能的信息,例如使用 zx_system_get_features 系统调用。

此外,内核仍然可以利用一些较新的硬件功能,例如不需要生成不同代码的 64kB 内存页面,而只需要在运行时查询这些功能是否存在。如果引入了这样的新功能,并且需要板级配置,则可以轻松引入定义关联标志的新参数 kernel_board_configs

向后兼容性

此 RFC 中建议的立即变更并未提高 Fuchsia 的最低硬件要求,因此对向后兼容性没有影响。此 RFC 所倡导的政策今后可能会提高最低要求。

安全注意事项

Fuchsia 使用或打算使用多项 CPU 功能来提升安全性或支持使用排错程序(随后可提高安全性)。这些变量通常不受此处讨论的编译器标记控制,因此无需担心。

值得注意的是:

测试

正确性:对 CPU 定位的更改绝不应损害正确性。我们通过持续的提交前和提交后测试来验证这一点。目前的系统足以确保这一点。

性能:对 CPU 定位的更改通常会影响性能。Fuchsia 的 Perfcompare 系统可用于验证任何此类更改,就像之前一样。

二进制文件大小:对 CPU 定位的更改通常会对二进制文件大小产生微妙的影响。具体来说,Fuchsia 目前最密切地跟踪 Astro 图像的大小,因为这是我们拥有的最大受限目标。立即更改不会降低此大小。将来会影响特定产品图片的更改可以审核并仔细考虑这些产品定义的所有者的权衡。

缺点、替代方案和未知情况

使用 CPU 定位时,有时相互冲突的目标需要在工程和业务之间做出许多权衡取舍。这些内容已在上文中进行了介绍。影响这些权衡的后续更改以及未来的调整机会和注意事项不在本 RFC 的讨论范围内。