Android NDK & ARM NEON instruction set extension support

-------------------------------------------------------------------------------------------


引言:

----------


Android NDK r3新增‘armeabi-v7a’的支持,它是基于ARMABI的,允许本地代码使用两个有用的指令集扩展:


-  Thumb-2,提供的指令(类似Thumb-1的紧凑指令)性能和32ARM不相上下。


-  VFPv3,提供硬件FPU寄存器和计算,能够显著的提升浮点性能。


更具体的说,默认‘armeabi-v7a’只支持VFPv3-D16(只能使用1664位硬件FPU寄存器)。


更多信息请阅读CPU-ARCH-ABIS相关内容。


ARMv7架构参考手册也定义了另外可选的指令集扩展“ARMAdvanced SIMD”,俗称“NEON”。它提供了:


-  一组有趣的标量/矢量指令和寄存器(后者映射到和FPU相同的芯片区域中),和MMX/SSE/3DNow一样!在x86的世界中。


-  要求VFPv3-D32(即 3264位硬件FPU寄存器,而不是最低的16)。


并不是所有的基于ARMv7Android 设备都支持NEON,对于那些支持NEON的,可以从标量/矢量指令获得明显的好处。


NDK支持模块的编译,甚至是NEON所支持的特定的源文件。这意味着,一个特定的编译器标志,可以同时使用GCC ARM NeonVFPv3-D32Intrinsics的描述在这里:


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后缀(用于指定的32ARM指令集,对于非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



运行时检查:

-------------------


像前面所说的,并不是所有的ARMv7android设备都支持NEON!因此运行时检查目标设备是否支持NEON是至关重要的。


为了进行检查,可以使用NDK自带的‘cpufeatures’库。请查看CPU-FEATURES相关内容。


你应该显示的检查android_getCpuFamily()是否返回ANDROID_CPU_FAMILY_ARM,还有android_getCpuFeatures()的返回值是否设置了ANDROID_CPU_ARM_FEATURE_NEON标志位,如:


#include      
 ...     
 ...      
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优化。