http://blog.csdn.net/ccjjnn19890720/article/details/7291228
版权声明:本文为博主原创文章,未经博主允许不得转载。
目录(?)[-]
这个学期的任务在开学的时候就已经定了下来.和老师聊过关于自己的想法,老师也表示了自己的想法,后来发现老师想的还是比我周到点.导师的意思是让我继续搞我的ARM板子,一直觉得搞这个没有搞PC机来的好.因为现在的板子的硬件已经提高了很多,可以说比以前的pc机都要强悍很多,在上面作开发让我觉得与在pc机上作开发没有什么区别.这样的思想在上个学期一直在我脑袋中存在呢,所以很多时候做事不是很积极的.但是后来导师说了,说你认为在上面做简单是因为你还没有深入进去,你还没了解它比较内涵的东西.那个时候的我觉得导师是忽悠我的,或者我真的只是想作一个软件开发者,而不喜欢自己去碰硬件,总是想和老师说这些.
大概老师是看穿我的思想了,在开学的时候就把任务给我安排好了.不能让我随便打酱油了,而且还和我说了我现在到底是往哪个方向发展.其实这个学期的任务看上去其实很简单的,就是把程序在板子能跑的更加快.那么要达到这个目的的最为主要的就是优化.导师的意思是说我要往底层发展,做一个硬件工程师,当然与那些画板子的工程师不一样的,我的人物就是提出自己的硬件要求和对程序进行最大和最深的优化.
一直作的都是C级别的优化,可是在上个学期的测试中发现这种级别的优化是很水的,提高的程度不是很客观.现在要往更为底层的发展.要接触硬件要接触汇编.这让我认清了自己的道路,而且本人对这个还是很感兴趣的.
接下来就要讲的就是NEON这个东西了.
一开始见到它还觉得它是一个可有可无的技术,后来看了很多的文章以后发现这个才是优化的突破口.
其实这个术语我很久以前就已经听过了,可以一直只有表面的理解,不就是单指令多数据流吗.难道这个还能比MIMD还要牛逼吗,一直觉得这是一种可有可无的技术,就算就在今天我还是觉得这样的技术就是过渡性的技术.可是今天看了一篇文章以后才发现它都有用之处.
通常我们进行多媒体处理的时候,很多的数据都是16位或者8位的,如果这些程序运行在32位的机器上,那么计算机有一部分的计算单元是没有工作的.所以这是一种浪费.为了更好的使用那些被浪费的资源.SIMD就应运而生了.SIMD这种技术就是使用一条指令,但对多个相同类型和尺寸的数据进行并行处理.就像我们现实生活中的好几个人都在做同一件事情那样,这样就可以将速度提升很多倍.
ARMv7体系结构介绍了增强性SIMD的扩展,它通过定义大量了在64位和128位的寄存器指令用来扩展了SIMD的概念.
据文档上了解NEON就是将增强性SIMD的扩展使用在ARM处理器上的实现.也就是说NEON是指用一种特定的方式去实现的过程.现在ARM Cortex-A8的系列是具有着NEON.具有NEON技术的处理器都会配备了32个64位的寄存器和16个128位的寄存器,它们分别被标识为(D0-D31),(Q0-Q15)NEON的指令集只是ARM和THUMB指令集中的子集,ARM和THUMB要管理所有程序流和同步的问题.NEON指令通常执行的就是:
- 内存的访问
- 在NEON寄存器和传统寄存器之间的数据拷贝
- 数据类型的转化
- 数据的处理
如何才能去优化NEON的代码呢??
这就是怎么样去使自己编写的代码能整合进NEON的技术,这样编译器就可以在编译的过程中尽可能的使用NEON的处理方式.
要使用NEON,那就使用NEON本身支持的指令效果最好了,那么NEON本身提供了什么样的指令呢??
就像上面所说那样,本身NEON指令提供的功能也很有限,主要在于数据的装载和存储,以及数据的处理.这应该是NEON指令的核心能力了.NEON的指令都是以V字母开头的.
VADD.I16 q0,q1,q2
这就是一个NEON的指令了,很明显的特点就是V开头,I主要用来表明是一个整型,16表示一个16位的整型,q0,q1,q2都是128位的寄存器(q打头的寄存器都是128位的).其实这个指令的意思就是让q1,q2中装载8个16位的数据,然后执行加法操作,最后放到q0中去.这么一个指令就完成了8次加法运算,也就是性能的提升.
像上面的指令,NEON还有很多.比如还提供比如RGB三个元素,分别取到3个不同的寄存器中,每一个寄存器中的元素要不都是R要不都是G要不都是B,这样一来就可以进行并行运算了.
既然知道了这些指令,那么使用到程序中去的话有几种手段呢??
- C语言级别的C语言级别的优化当然是对高级语言这个阶段来说的,对于NEON来说,这个级别的优化不是指那些很通用的优化手段,虽然那些能达到优化的作用,但是没有充分的利用NEON这的技术,所以很多时候你会发现,网上很多人说这个板子很厉害很厉害,可是你在上面开发的程序就是很慢很慢,这也就说明了你没有充分的利用其中的硬件资源.
C语言的优化可以分为两个手段:
- 内联函数
内联函数有可能会被误会成我们通常想的那样,主要是这个单词我翻译不正确(intrinsics).这样的函数可以被C和C++的程序所调用.看上去和别的函数没有很多的区别,最多也就名字比较古怪.但是其实当这个代码在被编译器编译的时候,它会被转化为有序的低级指令.这些指令就是NEON的指令了.所以这样就办到了在高级语言层次使用低级语言了.主要是很简单的可以使用.最为主要的就是程序员不用去接触汇编了,可以减小优化的难度.当然我可以说这样的优化效率没有使用汇编的来的高.
对于上面的这种技术其实就是ARM公司本身给你做好了一些函数,你就直接调用这些函数,这些函数在编译的时候就可以直接转化成NEON的汇编指令.为了支持这些内联的函数所以必须要包含头文件arm_neon.h.
#include
uint32x4_t double_elements(uint32x4_t input) { return(vaddq_u32(input, input)); } 像vaddq_u32这样的函数,gcc还提供很多很多,如果想知道更多可以查看gcc_neon.
当然使用了NEON技术以后必须还要通过在编译的时候加入-mfpu=neon
才能起到效果的.整个编译的命令就是arm-none-Linux-gnueabi-gcc -mfpu=neon intrinsic.c
- 汇编级别的
这个级别的优化是比较难的,但是也是最为有效的.通过对NEON指令的掌握然后对程序中消耗最大的那个部分进行汇编级别的改造,这样会有很大的区别.我昨天看了一篇文章上讲了,c级别的改造只提高性能1.5倍,但是汇编级别的就是7.5倍,从中可以看出之间的差距了吧.
- 使用库
ARM公司好像本身对NEON的技术做成了一个库(OPENMAX),里面都是ARM公司作了NEON作的优化程序.所以可以使用这些库函数来完成一些功能.可以在ARM
NEON的知识点还有很多,不过核心的就是这么一些其他就是它的扩展.要具体问题具体分析,对于现在我在做cortex-A8我觉得这个技术应该对我的帮助会很大...接下来就试试这个技术吧.