编译器的优化

编译器会对代码执行一定程度的优化,类似充分利用处理器的时钟周期实现并行化,如使用循环展开以减少循环的次数等。

编译器在执行优化的同时,必须保证程序本身的行为没有发生改变,所以有些优化是「不彻底的」。这些不可优化的内容大多都是动态化的变量,他们的值可能由于调用自身而发生改变。所以编译器对动态变量的优化是有局限性的,因为它不能保证调用自身的情况不会发生。

内联函数通常可以提高程序的性能,它可以减少内存地址的跳转次数和 ret 指令返回是造成的周期浪费,大多数编译器都会对较小的函数进行内联优化。

人工优化

由于编译器优化的局限性,有些动态变量自身调用的情况其实并非是程序员所期望的,所以在满足「程序目的」的情况下,进行适当的优化可以大幅的提高程序性能。

可进行的优化有:

一些限制因素

在优化足够充分的情况下,有些瓶颈可能不是在计算单元,而在于寄存器的个数(或称为 IO 瓶颈,寄存器的个数不够充足,便会向栈借空间,而从栈读取的延迟是远高于寄存器的),过多的累积变量可能造成适得其反的后果。

对分支预测的优化往往很难有十足的效果,因为各个处理器在设计时花了大量的精力在对分支预测的优化上,因此不必过分的关心分支预测的结果,往往选择将较大可能的判断,或许可以对分支预测起到积极作用。

正如第3章和第4章所说,条件传送 往往比 条件转移 有着更好的性能,所以在编写程序时,使用「先计算再判断」的方式往往比「先判断再计算」的方式更加有效。(在我使用 GCC 编译测试的几个程序中,编译器通常会选择自动将条件转移优化为条件传送)

注意内存操作的引用,下一步操作减少对上一步的引用可以提高性能,转移关键路径。