【发布时间】:2013-01-10 01:48:25
【问题描述】:
对于编译器如何实际优化,以及不同级别之间的区别(例如 gcc 的 -O2 与 -O3),我没有太多经验。因此,我不确定以下两个语句对于任意编译器是否等效:
for(i=0;i<10;++i){
variable1*variable2*gridpoint[i];
}
和
variable3=variable1*variable2;
for(i=0;i<10;++i){
variable3*gridpoint[i];
}
从处理时间的角度来看,只计算一次 variable1 和 variable2 的乘积是有意义的,因为它们在循环中不会改变。然而,这需要额外的内存,而且我不确定优化器对这种开销的影响有多大。如果你有一个来自纸/书的方程式并且想要将其转换为计算机可读的东西,第一个表达式是最容易阅读的,但第二个可能是最快的 - 特别是对于循环内有很多不变变量的更复杂的方程(我有一些非常讨厌的非线性微分方程,我希望在代码中可读)。如果我将变量声明为常量,这些是否会发生变化?我希望我的问题对任意编译器有意义,因为我同时使用 gcc、Intel 和 Portland 编译器。
【问题讨论】:
-
这称为“公共子表达式消除”。
-
在这种情况下,除非变量被标记为 volatile,否则整个循环将被消除,因为循环体中的表达式没有副作用。
-
或者死代码消除,因为上述两个 sn-ps 可以安全地从程序中消除,因为它们什么都不做:)
-
为了记录,
volatile变量是与内存空间区域相关联的变量,该区域可以在代码的正常流程之外发生变化......例如,映射的变量到微处理器的输入寄存器,或映射到时钟寄存器的变量。因此,每次访问它时,它都可能发生了变化,即使没有代码可以为它赋值。因此,编译器不会将其分解到循环之外。 -
答案是编译器“可以”做这些优化中的任何一个,但由于各种原因不需要也可能不会做任何这些优化。不要假设某些东西会被优化,而是尽可能写出最好的代码。
标签: c optimization