您的位置:首页 > 编程语言

代码优化规则

2008-03-24 21:16 316 查看
1、用空间换取时间规则(Space-For-Time Rules)
> 扩充数据结构。通常,通过给结构增加其他信息或改变结构内部的信息让它访问得更快能够减少对数据的常用操作所需的时间。
> 存储预先计算好的结果。只计算函数一次然后存储结果能够减少重复计算某一昂贵函数所需的成本。以后对该函数的请求就只需通过表查找来完成,而不需要重新计算该函数
> 高速缓存。必须降低经常访问的数据的访问成本。
> 延迟计算。直到需要时才对某一元素进行计算避免了对不必要元素的计算。
2、用时间换取空间规则(Time-For-Space Rules)
> 压缩。密集存储表示能够通过增加存储和检索数据所需的时间来降低存储成本。
> 解释器。用于表示一个程序所需要的空间通常可以通过使用可将通用操作序列进行简化表示的解释器而减少
3、循环规则(Loop Rules)
> 将代码移出循环。最好不要在循环的每次迭代中都执行特定的操作,而是将它放在循环外部,仅执行一次。
> 合并测试条件。高效的内部循环应该尽量少包含测试条件,最好只有一个。因此,程序员应该尽量使用其他退出条件来模拟循环中的一些退出条件。如顺序查找中哨兵的应用:在数据结构的边界上放一个哨兵来减少对是否已经查完整个结构的测试。
> 循环展开。解开一个循环能够消除修改下标的成本。同时有助于避免管道延迟,减少分支,并且增加指令层的并发执行。
> 传输驱动的循环解开(Transfer-Driven Loop Unrolling)。如果在普通的赋值中使用了一个成本很高的内部循环,那么通常或通过重复这些代码并改变对变量的使用来消除这些赋值。
> 消除无条件分支。在快速的循环中不应该包含无条件分支。这通常可由编译器优化选项来完成。
> 循环合并。如果两个邻近的循环操作作用在同一个元素集中,那么最好合并这两个操作部分,仅仅使用一个循环控制操作。
4、逻辑规则(Logic Rules)
> 利用代数恒等式。如果逻辑表达式的计算非常昂贵,就使用比较廉价的代数恒等表达式来替代它。
> 如果测试几个变量的单调非递减函数是不是超过了特定的阀值时,那么一旦达到了这个阀值,就不需要计算任何变量。比如,在循环中一旦达到了循环的目的(如找到所需的元素)就退出循环。
> 重新排序测试。在组织逻辑测试的时候,应该将廉价的经常成功的测试放在昂贵的很少成功的测试前面。
> 预先计算逻辑函数。可以通过查找一个表示小的有限域的表来代替该域的逻辑函数
> 消除布尔变量。用if-else语句替代对布尔变量v的赋值来消除布尔变量。
5、过程规则(Procedure Rules)
> 压缩函数层次。使用宏或内联函数来代替普通的函数调用(非递归)来减少运行时间。
> 利用常用情况。应该对函数进行组织来正确地处理所有情况以及高效地处理普通情况。
> 协同例程。通常,使用协同例程能够将多通道(multiple-pass)算法转换为单通道算法,即所谓的管道操作。
> 对递归函数进行转换。通过下面的转换能够减少递归函数的运行时间:
[将递归重写为迭代],通过使用一个显式的程序栈将递归转换为迭代
[如果函数的最后一步是递归地调用自身,那么使用一个到其第一条语句的分支来替换该调用,即消除尾递归。通过将该分支转换为循环来进行优化,这一般由编译器来进行优化]
[通常通过使用辅助过程能够更高效地解决这些小的子问题,而不是将问题的大小变为0或1]
> 并发。一个程序应该组织为尽可能多地使用低层硬件的并发功能。
6、表达式规则(Expression Rules)
> 编译时初始化。在程序执行之前,尽可能多地对变量进行初始化。
> 利用代数恒等式。如查表达式的计算非常昂贵,就应该使用较为便宜的代数恒等表达式替换之。如使用廉价的if语句替换内部循环中昂贵的C求余操作符%,使用左右移位来实现幂的乘或除。
> 消除通用的子表达式。如果连续两次计算了同一个表达式,并且两次计算中间,其所有变量都没有任何改动,那么第二次计算就可以通过保存第一次计算的结果并将其用于第二次而得到避免。
如今的编译器都能消除不包含函数调用的常用子表达式
> 配对计算。如果总是同时计算两个类似的表达式,那么就应该建立一个新的过程,将他们成对计算。
> 利用单词的并发。使用低层计算机体系结构的完整数据路径宽度计算昂贵的表达式。如通过直接操作char或int型的数据来多个比特位(8位或32位)的操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: