ARM Linux的优化主要涉及部分:
1.内核部分
2.应用程序部分
两者的主要区别在于:内核没有使用标准C库和涉及浮点运算。所以在针对内核和应用程序优化上有所区别。
优化一般涉及两个方面:空间和时间。一般情况我们只能选择最优,两种不可兼得。不过随着ARM新的核A15的推出(据说速度可以达到2.5G,看来ARM的野心也不小,虽然WINDOWS系统还不支持ARM,未来也不不一定)以及现在存储的技术和性价比不断提升,将来的开发主要应该会走PC的路,注重功能和可复用,可维护性。
首先工具链的选择很关键,好的工具会带来很大的提升,当然真正提高性能的还是靠代码编写的算法和质量。Linux使用的GNU工具链,而且现在很多组织和厂商推出了针对自己平台优化的GNU工具链。ARM工具链主推codesourery的G++工具链。其与ARM公司合作,也是ARM公司主推的工具。
对于内核的优化,主要在削减内核功能和修改过于复杂的功能。不过这部分功能需要对内核非常熟悉,而且内核中各个模块的组织和依赖也必须非常明确了解。
应用程序优化,主要涉及应用程序本身和其使用的库。
下面讲讲一些优化的手段,具体可以参考如下一些文档和网站:
CE Linux Forum两个WIKI:
http://elinux.org/Main_Page
http://tree.celinuxforum.org/CelfPubWiki/FrontPage
BLOG:http://blog.chinaunix.net/u/30686/
以及该博主写的两篇流传很广的文档:
嵌入式LINUX性能优化
嵌入式Linux内存与性能详解
1.加入特别体系结构有关参数进行优化。
-march=armv4t
-march=armv5te
-march=armv6
-march=armv7
具体参考编译器手册,这样产生的代码将针对该具体体系结构。同时在工具链提供针对各种体系结构的库时,一定要记得传递这个参数,否则编译器将使用默认编译器默认链接的库。
2.浮点操作
很多处理器没有浮点协处理,传统采用浮点模拟器机制来实现,即在内核配置时选择相关的浮点模拟器(如NWFPE),但是其实现一般采用未定义指令异常来操作,当浮点运算多时这样会大大降低性能,因为频繁的发生异常,进入系统模式的切换。解决办法是采用软浮点工具链。这样在编译时由编译器将浮点运算由浮点库代替,而浮点库采用的都是正常指令,同时能更好的优化,其比浮点模拟器要快些,具体多少,我没有进行很严谨的测试。
那么如果判断工具链是否支持软浮点的呢?在编译时加入-msoft-float看是否支持就知道了。
在网上看到一些资料:
交叉GCC与浮点处理
很多讲ARM Linux内核编译的文章或手册都会说
由于arm没有浮点协处理器,所以需要一个模拟浮点机制,
在配置内核时一定要选择一个浮点模拟器NWFPE,如下
--- At least one math emulation must be selected │ │
│ │ <*> NWFPE math emulation │ │
│ │ [ ] Support extended precision │ │
│ │ < > FastFPE math emulation (EXPERIMENTAL)
如果没有浮点模拟器,就会出现错误。比如未定义的指令:
init (1): undefined instruction: pc=4004b020
Code: e3a01000 00000000 00000000 00000000 (eca0420c)
实际上,即使使用了NWFPE,系统的浮点问题也并没有完全解决
NWFPE模拟浮点是利用了undefined instrction handler
即每次浮点指令操作,都会发生一次未定义指令异常(exception),
在这个异常的handler里面,用软件的方法仿真一个浮点指令
如果软件里的浮点运算比较多,那岂不是不停的请求CPU执行undefined instruction,然后产生异常?
答对了,内核模拟浮点指令事实上就是这么回事
这么做带来的后果是带来极频繁的exception,大大增加中断延迟
换句话说,降低系统实时性
另外,每发生一次浮点操作,都要陷入到exception,不难想见会带来极大的性能开销。
内核模拟浮点指令,要实现一个大的case switch
通常情况这个分支预测都会不命中,既要多浪费cpu clock
还会排空BTB,进一步降低后面分支预测命中率
怎么办?——使用软浮点!
软浮点支持是由交叉工具链提供的功能,与Linux内核无关
当使用软浮点工具链编译浮点操作时,编译器会用内联的浮点库替换掉浮点操作
使得生成的机器码完全不含浮点指令,但是又能够完成正确的浮点操作
由于是在编译时优化,这种方式能够让CPU即使作浮点运算时也能够执行连续的指令,减少程序分支
使用软浮点工具链编译产生的浮点操作速度较快
比NWFPE模拟快一个数量级
我们怎么知道交叉工具链是否支持软浮点呢?
很简单,使用编译命令时加上-msoft-float这个CFLAGS就可以了,比如
arm-linux-gcc test.c -msoft-float -o test
如果工具链支持软浮点,那么就可以生成可执行文件
如出错,对不起,该工具链不支持
另一个鉴定的方法,拿到一个编译产生的文件,使用
arm-linux-readelf -e test
可以打印出elf文件头信息
在里面看到software FP就是软浮点格式,否则不是
Flags: 0x202, has entry point, GNU EABI, software FP
3.根据GNU工具链规则,其优化是针对一个目标文件的。所以最好一个源文件里面只有一个功能函数,特别是作为库使用时。