圍紀實驗室
Advertisement

编译器最佳化(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
  • 递回最佳化
递回所耗费的额外时间非常多,将可化成循环的递回化成循环

参考资料[ | ]

Advertisement