ipv6域名查询-ipv6网络监控-免费域名解析查询

基于ARM的代码性能优化方法

发布日期:2021-01-12 20:43:15   来源 : 原创    作者 :稻草人    浏览量 :2825
稻草人 原创 发布日期:2021-01-12 20:43:15  
2825

导语:

征稿启事发出后,我们很快就收到投稿啦,非常开心:),也更加坚定了我们一直做下去的决心!现在将第一篇投稿分享给大家。


在ARM上做嵌入式编程时候,如果注意一些代码书写习惯,可以使代码运行速度得到优化,总结如下。

一.恰当的使用inline函数。

       对于一些频繁调用的代码量不太大的函数,使用inline是个很好的优化方式。因为arm每次调用函数都是有开销的:输入参数要通过r0~r3传递,如果大于4个,还要通过将多余的参数压栈传递;被调用函数内部还可能会有寄存器入栈出栈;还有程序计数器pc的跳转也有开销。但是当函数体比较大的时候多个地方内联可能会导致代码段增加,代码运行时候代码量加大可能导致降低缓存命中率,频繁更新缓存反而会降低代码的效率。

二. 常用指令优化

ARM上面做除法,取余是非常费时的操作。ARM 7 指令集中没有除法指令,其除法是通过调用C 库函数实现的。因此, 除法成了一个程序效率的瓶颈, 应尽量避免使用。常见的除2的整数次幂可以通过移位来实现,例如对8取余可以通过逻辑与7来实现。还可以将除法操作转换成乘法+查表来实现。

三. 循环的写法。

使用递减的循环可以比递增的循环高效。例如for(i=0;i<n;i++)循环条件编译成汇编为add i,#1;cmp i,n;blt loop_beginning需要三条汇编指令。但是for(i=n;i>0;i--)编译成汇编为subs i,#1;bgt loop_beginning 只需要两条指令。这是因为ARM指令后面加s可以和0比较更新状态位,这样可以节省一条指令。

四.函数参数的传递

arm函数传参和返回值都尽量使用int类型。函数参数的前四个是通过r0~r3传递的,返回值是通过r0传递的。如果输入参数大于4个,多出的参数会放到栈里面。对于一个大的结构体作为函数的参数,一定要传递结构体的指针,而不能将结构体作为函数的参数。例如void function(LargeStructure *a)和void function(LargeStructure a),前面的写法只需要使用r0就可以传递参数,但是后面的写法会把整个结构体成员都传递给函数,会造成大量的栈空间使用。

五.循环优化

对于嵌入式代码,循环体内的代码会重复执行好多次,因此对循环的代码尤其是双重循环的内层循环体优化会收到事半功倍的效果。

1)如果确定循环至少能做一次,则使用do-while比for循环能节省判断循环次数为0的情况。

2)如果循环体较为简单,可以适当的展开循环体,这样可以节省循环判断跳转的开销,也有利于更好的排指令流水。例如一个循环次数n可以确定是2的整数倍,就可以将循环体写两遍,循环次数变为n>>1;如果不确定,循环次数做n>>1次,最后再判断如果n为奇数再做一次即可。

3)尽量限制函数内部循环所用局部变量的数目,尽量不超过12个,以便编译器能把变量分配到寄存器减少临时变量入栈。

4)检查代码查看是否可以用一个局部变量来保存公共子表达式的值,保证该表达式只求一次值。

六.变量的使用

       因为arm寄存器都是32bit的,即使使用short类型也是放到一个寄存器里运算,所以内存不紧张的情况下可以使用整型数据。否则,编译器将要处理大于short和char取值范围的情况而添加代码。 
ARM
性能优化
Copyright2020 版权所有:深圳市稻田网络技术有限公司
云计算支持 反馈 枢纽云管理