NEON 支持

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

并非所有基于 ARMv7 的 Android 设备都支持 NEON,但支持的设备可能会因 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_getCpuFamily() 是否返回 ANDROID_CPU_FAMILY_ARM,以及 android_getCpuFeatures() 是否返回一个值,并且设置了 ANDROID_CPU_ARM_FEATURE_NEON 标记。例如:

    #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 优化的基准。