JEP 315: Improve Aarch64 Intrinsics | 改进 Aarch64 内部函数
摘要
在 AArch64 处理器上,改进现有的字符串和数组内部函数,并为 java.lang.Math
的 sin、cos 和 log 函数实现新的内部函数。
非目标
- 与其他架构的性能进行比较并与之匹配
- 仅针对单一的 ARM64 架构实现调整通用的 AArch64 端口内部函数以获得最佳性能
- 将内部函数移植到 ARM CPU 端口
动机
针对特定 CPU 架构的专用代码模式可以提高用户应用程序和基准测试的性能。
描述
内部函数用于利用 CPU 架构特定的汇编代码,这些汇编代码会替代给定的方法的通用 Java 代码来执行,从而提高性能。尽管大多数内部函数已经在 AArch64 端口中实现,但针对以下 java.lang.Math
方法的优化内部函数仍然缺失:
sin
(正弦三角函数)cos
(余弦三角函数)log
(数的对数)
本 JEP 旨在通过为这些方法实现优化的内部函数来弥补这一缺陷。
同时,尽管大多数内部函数已经在 AArch64 端口中实现,但一些内部函数的当前实现可能并非最优。具体来说,AArch64 架构的某些内部函数可能会受益于软件预取指令、内存地址对齐、多管道 CPU 的指令放置,以及用更快的指令或 SIMD 指令替换某些指令模式。
这包括(但不限于)诸如 String::compareTo
、String::indexOf
、StringCoding::hasNegatives
、Arrays::equals
、StringUTF16::compress
、StringLatin1::inflate
和各种校验和计算等典型操作。
根据内部函数的算法、最常见的内部函数用例以及 CPU 的特性,可以考虑以下更改:
- 使用 ARM NEON 指令集。如果创建了此类代码,则会在一个标志(如
UseSIMDForMemoryOps
)下放置,以便在现有算法有非 NEON 版本的情况下使用。 - 使用预取提示指令(PRFM)。此指令的效果取决于各种因素,如 CPU 硬件预取器的存在及其能力、CPU/ 内存时钟比率、内存控制器特性以及特定算法需求。
- 重新排序指令并减少数据依赖性,以允许在可能的情况下进行乱序执行。
- 如有必要,避免未对齐的内存访问。一些 CPU 实现会在跨 16 字节边界、dcache 行边界发出加载 / 存储指令时施加惩罚,或者对不同的加载 / 存储指令有不同的最佳对齐方式(例如,参见 Cortex A53 指南)。如果对齐版本的内部函数不会减慢对齐无关 CPU 上的代码执行速度,那么提高地址对齐性以帮助那些有惩罚的 CPU 可能是有益的,前提是它不会显著增加代码复杂性。
测试
- 将使用 JMH 基准测试在 Cavium ThunderX、ThunderX2 和 Cortex A53 硬件上测试内部函数的性能。
- 将使用
jtreg
测试套件测试功能的正确性。如果现有的测试库不能提供足够的覆盖范围,可能会创建额外的测试。
风险与假设
- 将努力实现性能最优的通用版本的 AArch64 内部函数。在不可能实现的情况下,可能需要为特定的硬件供应商编写专用版本的内部函数。
- 无法在所有 AArch64 硬件变体上进行测试和性能测量。我们将依赖 OpenJDK 社区在我们没有内部硬件的情况下进行测试,如果他们在提交补丁以供审查时认为有必要的话。
- 本 JEP 范围内的内部函数是特定于 CPU 架构的,因此更改它们不会影响共享的 HotSpot 代码。