编译器最佳化(Compiler Optimization)是在将原始程式码转为可执行档案的过程中,在不影响执行结果的前提下改变原始程式的内容以调整程式的特性。常见的最佳化有执行速度的最佳化、执行档大小的最佳化、占用内存的最佳化等等。本篇文章目前的示例都以Python程式语言为例。
循环最佳化[ | ]
- 平行化
- 自动将前后独立的循环进行平行化处理,使循环可以同时在数个不同的处理器上运作,以加快处理速度。
- 逻辑顺序变换
- 将原本在循环内部且与循环的执行结果无关的判断式移至循环外。例如这样的程式码
for i in range(1,5): if a == b: print i
- 由于循环内的判断式不会受到循环内容影响,故经过最佳化之后可以变成这样
if a == b: for i in range(1,5): print i
- 循环展开
- 将在编译时期已知圈数的循环展开,减少循环的控制需要的额外时间以及减少目的码中branch的数量,以使CPU的pipeline功能可以发挥得更好。
- 循环变数简化
- 若循环中用到的值都是循环变数的函数非而变数本身,改变循环变数运算的方法可以节省一些指令。
- 循环融合
- 若相邻的两循环跑相同的次数且相依,则可以合并两循环以减少循环控制需要的时间。如
for i in range(1,ndata): phones.append(data[i].phone) for j in range(1,ndata): addresses.append(data[j].address)
- 就会自动被简化成
for i in range(1,ndata): phones.append(data[i].phone) addresses.append(data[i].address)
目的码最佳化[ | ]
- 暂存器使用
- 把使用频率最高的变数直接存放在暂存器中,以得到最高的存取效能。
- 提出公因式
- 若产生出的代码中有数个一模一样的区块,则提出成为小型的函式;此举会增加执行的时间,但可以减少执行档的大小。
- 运算顺序重置
- 将部分不相关的运算改变顺序,以利提出公因式的进行。
- 指令结合
- 现代CISC系的CPU都有许多不同的指令方式可以做同一件事,可以在不影响结果的前提下调整指令(instruction)的顺序使数个指令可以被一个较高阶的CPU指令取代。
运算式最佳化[ | ]
- 重复运算缩减
- 将一条运算式中重复的部分集中,只运算一次。例如在
a = (c**6)+(15+(c**3))/2-(c**3)
- 当中,c的3次方只需要被计算一次。
- 已知常数替代
- 把在编译时期已经可以知道确切值的常数结合,避免在执行时期再次运算。例如
a = 5 b = a**2 + 639 - 199*a
- 便可以直接被替代成
a = 5 b = -331
- 递回最佳化
- 递回所耗费的额外时间非常多,将可化成循环的递回化成循环