NEON 支持

NDK 支持 ARM Advanced SIMD(通常称为 NEON),一种适用于 ARMv7 和 ARMv8 的可选指令集扩展。 NEON 提供标量/矢量指令和寄存器(与 FPU 共享),堪比 x86 中的 MMX/SSE/3DNow!。 要运行 NEON,则需要 VFPv3-D32(32 个硬件 FPU 64 位寄存器,而非最小值 16 个)。

并非所有基于 ARMv7 的 Android 设备都支持 NEON,但支持的设备可能会因其支持标量/矢量指令而受益匪浅。

NDK 支持模块编译,甚至可以编译支持 NEON 的特定源文件。

使用 LOCAL_ARM_NEON

要让 NDK 构建支持 NEON 的所有源文件,请在模块定义中纳入以下代码行: makefile LOCAL_ARM_NEON := true

如果您要构建特别包含仅有 NEON 代码的静态或共享库,构建支持 NEON 的所有源文件可能特别有用。

使用 .neon 后缀

LOCAL_SRC_FILES 变量列出源文件时,您可以选择使用 .neon 后缀表示要构建支持 NEON 的单个文件。 例如,以下代码构建一个支持 NEON 的文件 (foo.c),以及另一个不支持 NEON 的文件 (bar.c): makefile LOCAL_SRC_FILES := foo.c.neon bar.c

您可将 .neon 后缀与 .arm 后缀合并,以指定用于非 NEON 指令的 32 位 ARM 指令集(而非 Thumb2)。 在这种情况下,.arm 必须在 .neon 之前。 例如:可以是 foo.c.arm.neon,但不可以是 foo.c.neon.arm

构建要求

NEON 支持适用于 armeabi-v7aarm64-v8a ABI。 如果 NDK 构建脚本在尝试借助 NEON 支持进行构建时遇到其他 ABI,NDK 构建脚本将退出。 务必在 Android.mk 文件中运行如下检查代码:

# define a static library containing our NEON code
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
include $(CLEAR_VARS)
LOCAL_MODULE    := mylib-neon
LOCAL_SRC_FILES := mylib-neon.c
LOCAL_ARM_NEON  := true
include $(BUILD_STATIC_LIBRARY)
endif # TARGET_ARCH_ABI == armeabi-v7a

运行时检测

您的应用必须执行运行时检测,以确认支持 NEON 的机器代码能够在目标设备上运行。 这是因为并非所有基于 ARMv7 的 Android 设备都支持 NEON。 应用可以使用 NDK 随附的 cpufeatures 库执行此检查。

您应检查设置 ANDROID_CPU_ARM_FEATURE_NEON 标记后,android_getCpuFamily() 是否返回 ANDROID_CPU_FAMILY_ARM,以及 android_getCpuFeatures() 是否返回一个值。 例如:

#include <cpu-features.h>
...
...
if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
    (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0)
{
    // use NEON-optimized routines
    ...
}
else
{
    // use non-NEON fallback routines instead
    ...
}

...

对 x86 提供跨平台支持

NDK 支持使用第三方 NEON_2_SSE.h,将您现有的 ARM SIMD (NEON) 内建函数跨平台编译为 x86 SSE 代码。 如需了解有关此主题的详细信息,请参阅从 ARM NEON 到 Intel SSE 自动移植解决方案、提示及技巧

示例代码

hello-neon 示例举例说明如何同时使用 cpufeatures 库和 NEON 内建函数。 此示例对使用 C 版本的 FIR 过滤循环实现微小基准,对支持 NEON 的设备实现 NEON 优化的基准。