Android NDK & ARM NEON instruction set extension support
-------------------------------------------------------------------------------------------
引言:
----------
Android NDK r3新增‘armeabi-v7a’的支持,它是基于ARMABI的,允许本地代码使用两个有用的指令集扩展:
- Thumb-2,提供的指令(类似Thumb-1的紧凑指令)性能和32位ARM不相上下。
- VFPv3,提供硬件FPU寄存器和计算,能够显著的提升浮点性能。
更具体的说,默认‘armeabi-v7a’只支持VFPv3-D16(只能使用16个64位硬件FPU寄存器)。
更多信息请阅读CPU-ARCH-ABIS相关内容。
ARMv7架构参考手册也定义了另外可选的指令集扩展“ARMAdvanced SIMD”,俗称“NEON”。它提供了:
- 一组有趣的标量/矢量指令和寄存器(后者映射到和FPU相同的芯片区域中),和MMX/SSE/3DNow一样!在x86的世界中。
- 要求VFPv3-D32(即 32个64位硬件FPU寄存器,而不是最低的16)。
并不是所有的基于ARMv7的Android 设备都支持NEON,对于那些支持NEON的,可以从标量/矢量指令获得明显的好处。
NDK支持模块的编译,甚至是NEON所支持的特定的源文件。这意味着,一个特定的编译器标志,可以同时使用GCC ARM Neon和VFPv3-D32。Intrinsics的描述在这里:
http://gcc.gnu.org/onlinedocs/gcc/ARM-NEON-Intrinsics.html
LOCAL_ARM_NEON:
---------------------------
在module中定义LOCAL_ARM_NEON为‘true’,这样NDK编译的文件将支持NEON指令。这是非常有用的,如果你编译的静态或动态库包含NEON代码路径的话。
使用.neon后缀:
------------------------
当用LOCAL_SRC_FILES变量列出源文件的时候,你可以使用一个可选的后缀.neon来表明你的代码支持Neon。例如:
LOCAL_SRC_FILES :=foo.c.neon bar.c
这样只有‘foo.c’支持NEON指令。
注意.neon后缀也可以和.arm后缀(用于指定的32位ARM指令集,对于非NEON指令集)一起使用,但是必须在arm的后面。
换句话说,‘foo.c.arm.neon’可以工作,但是‘foo.c.neon.arm’不行。
编译条件:
----------------
NEON只支持针对‘armeabi-v7a’的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
运行时检查:
-------------------
像前面所说的,并不是所有的ARMv7的android设备都支持NEON!因此运行时检查目标设备是否支持NEON是至关重要的。
为了进行检查,可以使用NDK自带的‘cpufeatures’库。请查看CPU-FEATURES相关内容。
你应该显示的检查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
...
}
...
示例代码:
---------------
可以查看NDK sample中的‘hello-neon’代码,学习如何同时使用‘cpufeatures‘库和Neon指令。
这个示例使用c语言实现了一个微小的基准FIR滤波器环路,对于支持NEON的设备使用了NEON优化。