文章的内容是从Android开发者官网扒的,为了防止再登不上去,记录一下。
x86 支持
本页内容
- 概览
- ARM NEON 内联函数支持
- 独立工具链
- 兼容性
NDK 引入对 x86
概览
如需生成 x86 机器代码,请将 x86 添加到 Application.mk 文件中的 APP_ABI
APP_ABI := armeabi armeabi-v7a x86
如需了解有关定义
APP_ABI 变量的详细信息,请参阅
Application.mk。
构建系统将生成的库放入 $PROJECT/libs/x86/(其中 $PROJECT 表示您的项目的根目录)并其嵌入 /lib/mips/
在兼容的基于 x86 的设备上安装 APK 时,Android 软件包提取这些库,将它们置于应用的私有数据目录下。
在 Google Play 商店中,服务器过滤应用,以便消费者只能看到可在其设备所配备的 CPU 上运行的原生库。
通过与标准 ARM NEON 内联函数标头 arm_neon.h
此解决方案的特性包括下列各项:
默认使用 SSE 到 SSSE3 指令集将 ARM NEON 移植到 Intel SSE,涵盖所有 NEON 函数的 93% 左右(1869 个(总数为 2009 个))。
将 ARM NEON 128 位矢量重新定义为均等的 x86 SIMD 数据。
如果存在 1:1 对应关系,则将来自 ARM NEON 的一些函数重新定义为 Intel SSE。
使用 Intel SIMD(如果它将生成一个性能结果)实现某些 ARM NEON 函数。
使用序列化解决方案实现部分剩余的 NEON 函数,并发送相应的“低性能”编译器警告。
性能
大多数情况下,您应该能够取得类似于从 ARM NEON 代码获取的性能。 实现最佳结果的建议包括:
- 使用 16 位数据对齐以实现更快地加载和存储速度。
- 避免将 NEON 函数与常量一起使用。使用常量会导致因必须加载常量而造成的性能损失。 如果您必须使用常量,则尝试在热点环路之外初始化它们。 如果可以,将它们替换为逻辑运算和比较运算。
- 尽量避免使用标记为“依次实现”的函数,因为它们需要将来自寄存器的数据存储到内存。 替代的做法是依次处理它们并重新加载。您可以更改用于矢量化整个端口的数据类型或算法,而不是进行序列化。
如需了解有关此主题的详细信息,请参阅从 ARM NEON 到 Intel SSE – 自动移植解决方案提示与技巧。
与 ARM 版本的已知差异
大多数情况下,对于 NEON,x86 实现生成与 ARM 实现相同的结果。x86 实现几乎始终传递 NEON 测试。 但在几个极端情况下,x86 实现生成不同于其 ARM 实现的结果。 已知的不兼容性如下:
VRECPS/VRECPSQ
- 如果一个操作数为 +/- 无限值,则第二个操作数为 +/- 0.0:
- 在 ARM CPU 上,这些指令返回一个等于 2.0 的结果元素。
- x86 CPU 返回
QNaN Indefinite
- 。如需了解有关 QNaN 浮点不定数的详细信息,请参阅 Intel® 64 和 IA-32 架构软件开发者手册中的“4.2.2 浮点数据类型”与“4.8.3.7 QNaN 浮点不定数”。
VRSQRTS/VRSQRTSQ
- 如果一个操作数为 +/- 无限值,则第二个操作数为 +/- 0.0:
- 在 ARM CPU 上,这些指令返回一个等于 1.5 的结果元素。
- x86 CPU 返回
QNaN Indefinite
- 。如需了解有关 QNaN 浮点不定数的详细信息,请参阅 Intel® 64 和 IA-32 架构软件开发者手册中的“4.2.2 浮点数据类型”与“4.8.3.7 QNaN 浮点不定数”。
VMAX/VMAXQ
- 如果一个操作数为 NaN,或两个操作数均为 +/- 0.0:
- 在 ARM CPU 上,浮点最大值工作原理如下:
- max(+0.0, -0.0) = +0.0。
- 如果任意输入为 NaN,则对应的结果元素为默认 NaN。
- 如需有关此条件和结果的详细信息,请参阅 ARM 编译器工具链汇编程序参考,忽略“被取代”水印。
- 在 x86 CPU 上,浮点最大值工作原理如下:
- 如果其中一个源操作数为 NaN,则返回第二个源操作数。
- 如果两个源操作数均等于 0,则返回第二个源操作数。
- 如需了解有关这些条件和结果的详细信息,请参阅 Intel® 64 和 IA-32 架构软件开发者手册的第 1 册附录 E 部分 E.4.2.3 和第 2 册第 3-488 页。
VMIN/VMINQ
- 如果一个操作数为 NaN,或两个操作数均为 +/- 0.0:
- 在 ARM CPU 上,浮点最小值工作原理如下:
- min(+0.0, -0.0) = -0.0。
- 如果任意输入为 NaN,则对应的结果元素为默认 NaN。
- 如需有关此条件和结果的详细信息,请参阅 ARM 编译器工具链汇编程序参考,忽略“被取代”水印。
- 在 x86 CPU 上,浮点最小值工作原理如下:
- 如果其中一个源操作数为 NaN,则返回第二个源操作数。
- 如果两个源操作数均等于 0,则返回第二个源操作数。
- 如需了解有关这些条件和结果的详细信息,请参阅 Intel® 64 和 IA-32 架构软件开发者手册的第 1 册附录 E 部分 E.4.2.3 和第 2 册第 3-497 页。
VRECPE/VRECPEQ
- 这些指令在 ARM 和 x86 CPU 上提供不同程度的准确性。如需了解有关这些差异的详细信息,请参阅 ARM 网站上的如何使用 VRECPE/VRECPEQ 进行反向预估?以及 Intel® 64 和 IA-32 架构软件开发者手册第 2 册第 4-281 页。
VRSQRTE/VRSQRTEQ
- 这些指令在 ARM 和 x86 CPU 上提供不同程度的准确性。如需了解有关这些差异的详细信息,请参阅 RealView 编译工具汇编程序指南以及 Intel® 64 和 IA-32 架构软件开发者手册第 2 册第 4-325 页。
- 如果某个操作数为负数或负无限大,则
- 在 ARM CPU 上,这些指令默认返回一个(正的)NaN。如需了解有关此结果的详细信息,请参阅 ARM 编译器工具链汇编程序参考。
- 在 x86 CPU 上,这些指令返回一个(负的)QNaN 不定数。如需了解有关此结果的详细信息,请参阅 Intel® 64 和 IA-32 架构软件开发者手册第 1 册附录 E 部分 E.4.2.3。
示例代码
如果您的项目确保添加 arm_neon.h 标头,则在您的 APP_ABI 的定义中定义 include x86。 然后,构建系统将您的代码移植到 x86。
有关将 ARM NEON 移植到 x86 SSE 的原理的示例,请参阅 hello-neon 示例。
独立工具链
您可以将 x86 ABI 纳入您自己的工具链中。如需了解详细信息,请参阅独立工具链。
兼容性
x86 支持至少需要 Android 2.3 版本(Android API 级别 9)。如果您的项目文件面向较早的 API 级别,但添加 x86 作为目标平台,则 NDK 构建脚本自动为您选择正确的原生平台标头/库的集合。