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. To function, it requires VFPv3-D32 (32 hardware FPU 64-bit registers, instead of the minimum of 16).
Not all ARMv7-based Android devices support NEON, but devices that do may benefit significantly from its support for scalar/vector instructions.
The NDK supports the compilation of modules or even specific source files with support for NEON.
Using LOCAL_ARM_NEON
To have the NDK build all source files assuming NEON support, include the
following line in your module definition:
makefile
LOCAL_ARM_NEON := true
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.
Using the .neon Suffix
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:
makefile
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.
Build Requirements
NEON support works with the armeabi-v7a
and arm64-v8a
ABIs. If the NDK
build scripts encounter other ABIs while attempting to build with NEON support, the NDK build
scripts exit. It is important to use checks like the following in your
Android.mk
file:
# 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
Runtime Detection
Your app must perform runtime detection to confirm that NEON-capable machine
code can be run on the target device. This is because not all ARMv7-based
Android devices support NEON. The app can perform this check using the
cpufeatures
library
that comes with the NDK.
You should check that android_getCpuFamily()
returns ANDROID_CPU_FAMILY_ARM
and that android_getCpuFeatures()
returns a value with the
ANDROID_CPU_ARM_FEATURE_NEON
flag set. For example:
#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 ... } ...
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.