测试平台:
OMAP3430 SDP。
注意点:默认TI 给的uImage或者config 都是不支持neon的,需要重新make menuconfig,来enable这个功能。
参考:
http://tiexpressdsp.com/wiki/index.php?title=FAQ_OMAP35x_Linux_PSP#How_to_enable_the_NEON_coprocessor.3F
TOOLCHAIN:
arm-2007q3。 这个是GCC 官方支持neon的第一款。
编译选项:(针对内联的,汇编的话后面几个可以不用,担放着也没有问题)
CFLAGS = -s -save-temps -static -Wall -O3 -march=armv7-a -mtune=cortex-a8 -mcpu=cortex-a8 -mfloat-abi=softfp -mfpu=neon -ftree-vectorize -fomit-frame-pointer -ffast-math
Neon参考文献:
从ARM 官方上下载DUI0204IC_rvct_assembler_guide / DUI0348BC_rvct_comp_ref_guide, 两个都有中文版本,看起来很方便。配合最新的arm_architecture_reference_manual,应该足够了。
优化方法
两种方法我都尝试了下:
1: 使用内联
http://gcc.gnu.org/onlinedocs/gcc/ARM-NEON-Intrinsics.html
2:直接使用汇编
在简单函数的时候,两种差异不大;担担随着功能负责,使用内联会导致寄存器分配不够,反复压/出栈,而性能降低。同时使用内联也没有办法调整好流水线,(感觉NEON的大多数指令包括ADD等,都不是单周期的的,具体几个周期,我没有查到)。如果用汇编调整好的话,一般能够提高30+%
感觉:
和一般SIMD 指令差不多,支持16个128bit的寄存器。可以看成 16×8bit;8×16bit; 4×32bit...。指令功能还是很全的,甚至什么max,倒数都能够支持。也支持直接读/写chuncky数据BRG,YUYV啥的,简单的IF/ELSE也能支持。
用内联写的话很方便,函数合适的话,估计半天一个很轻松,一般优化个2 -3倍没问题。如果不够的话,就用ASM精细搞下。
不足:
我遇到一个优化失败的地方。程序是个梯度计算,本来是很合适的。担输入数据和目的数据都是YUYV,而我们只要处理Y好了。结果NEON必须同时读入YUYV(再展开成planar),这样多读/写了一倍数据,结果把性能托慢了。 这个模块计算太简单,ARM本身已经很快了,读写数据已经是瓶颈了,NEON的多读写数据就把优化的效果给干掉了。如果NEON能够支持“跳”着读/写,就好了,^_^。