Many projects use native code to improve performance. One advantage of developing in NDK over SDK is that we can build different packages for different CPUs, which is the topic of this recipe.
Please read the Building Android NDK application for different ABIs recipe before going through this one.
The following steps build Android NDK applications for different CPU features.
samples/hello-neon
folder of the Android NDK folder. Then click on Finish.samples/hello-neon/jni
folder. Type the command "ndk-build
" to build the binaries.Android devices are roughly divided by ABIs. However, different devices with the same ABI can have different CPU extensions and features. These extensions and features are optional and therefore we don't know whether a user's device has them until runtime. Detecting and making use of these features can sometimes improve app performance significantly on certain devices.
Android NDK contains a library named cpufeatures
,
which can be used to detect the CPU family and optional features at runtime. As illustrated in the sample code, the following steps indicate how to use this library:
Android.mk
as follows:LOCAL_STATIC_LIBRARIES := cpufeatures
Android.mk
file, import the cpufeatures
module:$(call import-module,cpufeatures)
<cpu-features.h>
.cpufeatures
provides only three functions:AndroidCpuFamily android_getCpuFamily();
It returns an enum. The supported CPU families are listed in the section to follow.
ANDROID_CPU_FAMILY_MIPS ANDROID_CPU_FAMILY_MIPS ANDROID_CPU_FAMILY_ARM
1
if the feature is available. The function prototype is as follows:uint64_t android_getCpuFeatures();
For the ARM CPU family, the supported CPU feature detections are as follows:
ANDROID_CPU_ARM_FEATURE_ARMv7
: It means that the ARMv7-a instruction is supported.ANDROID_CPU_ARM_FEATURE_VFPv3
: It means that the VFPv3 hardware FPU instruction set extension is supported. Note that this refers to VFPv3-D16, which provides 16 hardware FP registers.ANDROID_CPU_ARM_FEATURE_NEON
: It means that he ARM Advanced SIMD (also known as NEON) vector instruction set extension is supported. Note that such CPUs also support VFPv3-D32, which provides 32 hardware FP registers.For the x86 CPU family, the supported CPU feature detections are as follows:
We can do a "&
" operation to detect if a feature is available or not, as follows:
uint64_t features = android_getCpuFeatures(); if ((features & ANDROID_CPU_ARM_FEATURE_NEON) == 0) { //NEON is not available } else { //NEON is available }
Get the number of CPU cores on the device:
int android_getCpuCount(void);
There are a few more noteworthy points about CPU features on Android.
The cpufeatures
library can only detect a limited set of CPU features. It is possible to implement our own CPU detection mechanisms. By looking at the NDK source code at /sources/android/cpufeatures/
, one can find that the cpufeatures
library essentially looks at the /proc/cpuinfo
file. We can read this file and parse the content in our application. The following is a screenshot of the file content:
Please refer to the Android project cpuinfo
, available in the book's website for how to do this programmatically.
There are a few approaches to building native code for different CPU features:
helloneon-intrinsics.c
file is only compiled for armeabi-v7a ABI.libmylib-neon.so
and libmylib-vfpv3.so
. We detect the CPU feature at runtime and load the appropriate library.