循环优化
来源:互联网 发布:根据json生成实体类 编辑:程序博客网 时间:2024/05/18 03:42
循环优化
在大多数程序中,循环是一种常见的结构。由于大多数执行时间都耗费在循环上,因此有必要对循环做优化。
循环中止
循环中止条件要小心使用,否则会产生错误。一般有:
经常写递减到0的循环,使用简单的条件。
经常使用一个无符号整型的计数器,然后测试是否等于0。
显示了两个例子实现了计算 n!
,两个例子都显示了循环终止。第一个实现使用递增循环计算 n!
,而第二个实现使用递减循环计算 n!
。
表 4.1. C 递增和递减循环的C代码
int fact1(int n){ int i, fact = 1; for (i = 1; i <= n; i++) fact *= i; return (fact);}
int fact2(int n){ unsigned int i, fact = 1; for (i = n; i != 0; i--) fact *= i; return (fact);}
表 4.2 显示了以上两个例子经过编译器编译之后产生汇编代码,C 代码都使用编译器选项 -O2
-Otime
。
表 4.2. C 递增和递减循环的汇编代码
fact1 PROC MOV r2, r0 MOV r0, #1 CMP r2, #1 MOV r1, r0 BXLT lr|L1.20| MUL r0, r1, r0 ADD r1, r1, #1 CMP r1, r2 BLE |L1.20| BX lr ENDP
fact2 PROC MOVS r1, r0 MOV r0, #1 BXEQ lr|L1.12| MUL r0, r1, r0 SUBS r1, r1, #1 BNE |L1.12| BX lrENDP
比较 表 4.2 显示了在递增循环汇编代码中的 ADD
/CMP
指令对在递减循环汇编代码中被替换成了一个单指令 SUBS
。这是由于与0比较可以进行优化。
为了保存循环中的一条指令,变量 n
在循环中不需要保存,因此变量的用法在递减汇编代码也要保存。这使得容易分配寄存器。
在初始化循环计数器时一般将其设为需要重复的次数,然后递减到0。这也同样适合于while 和 do while 语句。
循环展开
对于一些比较小的循环可以被展开以获得更高的执行速度,但可能代码长度增加。当循环被展开后,循环计数器值的刷新次数较少且跳转也较少。如果循环次数较少,完全可以展开,循环的开消几乎没有。ARM 编译器可在选中 -O3
-Otime
时自动展开循环。否则,需要源代码里展开。
注意
手动展开循环可能隐藏了循环的特点使得编充程序不能识别循环而没有对其进行循环的其它优化。
展开循环的好处与坏处都在 表 4.3 中有显示。两个程序通过移位后测试最低位以此来计算位数。
第一种方法是用一个循环计算位数。第二种方法将循环展开,一次循环计算4次,因此 n
每次移4位,减少了循环次数。这样编译器可以更好的优化。
Table 4.3. 展开和非展开计算位数的C 代码
int countbit1(unsigned int n){ int bits = 0; while (n != 0) { if (n & 1) bits++; n >>= 1; } return bits;}
int countbit2(unsigned int n){ int bits = 0; while (n != 0) { if (n & 1) bits++; if (n & 2) bits++; if (n & 4) bits++; if (n & 8) bits++; n >>= 4; } return bits;}
表 4.4 显示了 表 4.3 中例子通过编译器产生的汇编代码,这些C代码在编译时要使用选项 -O2
。
Table 4.4. 展开和非展开计算位数的汇编代码
countbit1 PROC MOV r1, #0 B |L1.20||L1.8| TST r0, #1 ADDNE r1, r1, #1 LSR r0, r0, #1|L1.20| CMP r0, #0 BNE |L1.8| MOV r0, r1 BX lrENDP
countbit2 PROC MOV r1, r0 MOV r0, #0 B |L1.48||L1.12| TST r1, #1 ADDNE r0, r0, #1 TST r1, #2 ADDNE r0, r0, #1 TST r1, #4 ADDNE r0, r0, #1 TST r1, #8 ADDNE r0, r0, #1 LSR r1, r1, #4|L1.48| CMP r1, #0 BNE |L1.12| BX lrENDP
对于ARM7,在最左边的那种实现方法的汇编代码中检测一位需要6个 周期。但它的代码仅有9条指令。而右边的那种展开循环的方法,每次循环检测4位,平均每位只需3周期。它的代价是较大的代码--15条指令。
- 循环优化
- 循环优化
- 循环优化
- 前端性能优化:循环优化
- 嵌套循环的优化。。。
- 循环嵌套优化!!
- 循环的优化
- for循环的优化
- For 循环的优化
- For 循环的优化
- Android launcher 循环优化
- for循环优化方式
- 多重循环的优化
- 代码优化:多重循环
- 双重for循环优化
- c语言循环优化
- cuda优化-展开循环
- for循环优化策略
- Java 面试题
- MTK调试入门之一 --- TRACE使用的技巧
- 房价为何还会涨?
- JS遍历所有以TextBox_开头匹配的文本框
- 虚拟机安装FC10,上网设置,smb共享设置 (1)
- 循环优化
- 把扫描文件转变为word文档的最实用的四款OCR识别软件
- dropdownlist绑定的二种方法
- HO~HO~~入住CSDN博客了~~~
- 编写一个文件目录常用操作的类
- SQL Server死锁总结
- mtk category9 和category61都是画全屏,可以画一张图和一段文字。但区别是:
- IncrediBuild 加速原理
- 使用UI Automation实现自动化测试 -4.1