The NDK supports ARM Advanced SIMD, commonly known as Neon, an optional instruction set extension for ARMv7 and ARMv8. Neon provides scalar/vector instructions and registers (shared with the FPU) comparable to MMX/SSE/3DNow! in the x86 world.
Not all ARMv7-based Android devices support Neon, but devices that do may benefit significantly from its support for scalar/vector instructions.
All ARMv8-based devices support Neon.
The NDK supports the compilation of modules or even specific source files with support for Neon. You can use Neon intrinsics in C and C++ code to take advantage of the Advanced SIMD extension. The Neon Programmer's Guide for Armv8-A provides more information about Neon intrinsics and Neon programming in general.
Build
Enable Neon globally
ndk-build
ndk-build does not support enabling Neon globally. To enable Neon an entire ndk-build application, apply the per-module steps to every module in your application.
CMake
Pass -DANDROID_ARM_NEON=ON
when invoking CMake. If building with Android
Studio/Gradle, set the following option in your build.gradle:
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_ARM_NEON=ON"
}
}
}
}
Enable Neon per module
ndk-build
To build all the source files in an ndk-build module with NEON, add the following to the module definition in your Android.mk:
LOCAL_ARM_NEON := true
CMake
To build all the source files in a CMake target with NEON, add the following to your CMakeLists.txt:
if(ANDROID_ABI STREQUAL armeabi-v7a)
set_target_properties(${TARGET} PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()
Where ${TARGET}
is replaced with the name of your library.
It can be especially useful to build all source files with Neon support if you want to build a static or shared library that specifically contains Neon-only code.
Enable Neon per source file
ndk-build
When listing source files for your LOCAL_SRC_FILES
variable, you have the
option of using the .neon
suffix to indicate that you want to build
individual files with Neon support. For example, the following builds one
file (foo.c
) with Neon support and another (bar.c
) without:
LOCAL_SRC_FILES := foo.c.neon bar.c
You can combine the .neon
suffix with the .arm
suffix, which specifies
the 32-bit ARM instruction set (instead of Thumb2) for non-Neon instructions.
In such a case, .arm
must come before .neon
. For example: foo.c.arm.neon
works, but foo.c.neon.arm
does not.
CMake
To build a specific source file with Neon, add the following to your CMakeLists.txt:
if(ANDROID_ABI STREQUAL armeabi-v7a)
set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -mfpu=neon)
endif()
Runtime detection
Not all ARMv7-based Android devices support Neon. For maximum compatibility, 32-bit code should perform runtime detection to confirm that Neon code can be run on the target device. The app can perform this check using any of the options mentioned in CPU features.
As an alternative, it's possible to filter out incompatible devices on the Google Play Console. You can also use the console to see how many devices this would affect.
Cross-platform support for x86
NDK supports cross-platform compilation of your existing ARM SIMD (Neon) instrinsic functions into x86 SSE code, through the use of the third-party NEON_2_SSE.h. For more information on this topic, see From ARM NEON to Intel SSE-the automatic porting solution, tips and tricks.
Sample code
The hello-neon sample
provides an example of how to use the cpufeatures
library and Neon intrinsics
at the same time. This sample implements a tiny benchmark for a FIR filter loop
with a C version and a Neon-optimized version for devices that support Neon.