Neon 支持

NDK 支持 ARM 高级 SIMD(通常称为 Neon),一种适用于 ARMv7 和 ARMv8 的可选扩展指令集。Neon 提供标量/矢量指令和寄存器(与 FPU 共享),与 x86 中的 MMX/SSE/3DNow! 类似。

几乎所有基于 ARMv7 的 Android 设备都支持 Neon,包括搭载 API 级别 21 或更高级别的所有设备。NDK 默认启用 Neon。

所有基于 ARMv8 的 Android 设备都支持 Neon。

NDK 支持模块编译,甚至可以编译支持 Neon 的特定源文件。您可以在 C 和 C++ 代码中使用 Neon 内建函数来充分利用高级 SIMD 扩展指令集。针对 Armv8-A 的 Neon 程序员指南详细介绍了 Neon 内建函数和 Neon 编程的概况。

构建

全局启用 Neon

ndk-build

ndk-build 不支持全局启用 Neon。要为整个 ndk-build 应用启用 Neon,请对应用中的每个模块逐一执行启用步骤。

CMake

调用 CMake 时传递 -DANDROID_ARM_NEON=ON。如果使用 Android Studio/Gradle 进行构建,请在 build.gradle 中设置以下选项:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_ARM_NEON=ON"
            }
        }
    }
}

为每个模块启用 Neon

ndk-build

要使用 NEON 在 ndk-build 模块中构建所有源文件,请将以下内容添加到 Android.mk 的模块定义中:

LOCAL_ARM_NEON := true

CMake

要使用 NEON 在 CMake 目标中构建所有源文件,请将以下内容添加到 CMakeLists.txt 中:

if(ANDROID_ABI STREQUAL armeabi-v7a)
    set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()

其中 ${TARGET} 替换为您的库名称。

如果您要构建仅包含 Neon 代码的静态库或共享库,那么构建支持 Neon 的所有源文件将十分有用。

为每个源文件启用 Neon

ndk-build

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

LOCAL_SRC_FILES := foo.c.neon bar.c

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

CMake

要使用 Neon 构建特定的源文件,请将以下内容添加到 CMakeLists.txt 中:

if(ANDROID_ABI STREQUAL armeabi-v7a)
    set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()

运行时检测

几乎所有基于 ARMv7 的 Android 设备都支持 Neon,包括搭载 API 级别 21 或更高级别的所有设备。NDK 默认启用 Neon。为实现最大兼容性,32 位代码可执行运行时检测,以确认 Neon 代码能够在目标设备上运行。应用可以使用 CPU 功能中提及的任一选项执行此检查。

另外,您也可以在 Google Play 管理中心中过滤掉不兼容的设备。还可以使用管理中心查看这会影响到多少设备。

对 x86 提供跨平台支持

NDK 支持使用第三方 NEON_2_SSE.h 将您现有的 ARM SIMD (Neon) 内建函数跨平台编译到 x86 SSE 代码中。要详细了解此内容,请参阅 From ARM NEON to Intel SSE-the automatic porting solution, tips and tricks(从 ARM NEON 到 Intel SSE:自动移植解决方案、提示与技巧)。

示例代码

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