【发布时间】:2015-07-27 15:43:07
【问题描述】:
我正在使用 GCC 编译器测试 C/C++ 中的各种优化。我目前有一个包含多个嵌套 if 语句的循环。条件是在程序执行开始时计算的。它看起来有点像这样:
bool conditionA = getA();
bool conditionB = getB();
bool conditionC = getC();
//Etc.
startTiming();
do {
if(conditionA) {
doATrueStuff();
if(conditionB) {
//Etc.
} else {
//Etc.
}
} else {
doAFalseStuff();
if(conditionB) {
//Etc.
} else {
//Etc.
}
}
} while (testCondition());
endTiming();
doATrueStuff() 是一个内联函数,它执行一些简单的数值计算,因此调用它没有开销。
不幸的是,条件不能预先定义,它们必须在运行时计算。我们甚至无法可靠地预测它们是真是假的可能性。 getA() 也可能是 rand()%2。但是一旦计算出来,它们的值就永远不会改变。
我想到了两种解决方案,一种是全局函数指针,用于在循环中调用适当的函数,如下所示:
void (*ptrA)(void);
//Etc.
int main(int argc, char **argv) {
//...
if (conditionA) {
ptrA=&aTrueFunc;
} else {
ptrA=&aFalseFunc;
}
//...
do {
(*ptrA)();
} while (testCondition());
//...
}
这样我可以消除循环中的所有分支,但是我将有多个函数调用的开销减慢我的速度。
或者我可以简单地为每种条件组合使用不同的循环,如下所示:
if(conditionA) {
if(conditionB) {
do {
//Do A == true B == true stuff
} while (testCondition());
} else {
do {
//Do A == true B == false stuff
} while (testCondition());
}
} else {
//Etc.
}
但是,一旦开始有太多条件,这就不那么优雅了,并且不可能有效地做到这一点,因为对于 X 条件,需要编写 2^X 循环。
有没有更优雅/更快的方法来优化它?
这是否有任何意义,或者编译器会以某种方式理解条件在循环期间不会改变并自行优化?
出于好奇,是否有另一种编程语言可以使编写此类代码更容易/可能?还是只有在程序加载到内存后使用汇编来更改程序的指令才能实现?
【问题讨论】:
-
第一个想法似乎没有比原来更多的函数调用。
-
如果条件在循环内没有改变,CPU 可能会很好地进行分支预测。
-
看来您已经拥有了 2^X 个不同的块。
-
关于编译器的作用,我建议您在 gcc 命令行中添加 -fdump-tree-optimized 并查看生成的文件。它以相当易读的格式显示高级优化的结果。
-
在您花费大量时间尝试此类微优化之前,明智的做法是评估是否有任何显着收益。例如,如果你完全消除条件(选择特定的条件值模式),你能测试它的速度有多快吗?
标签: c++ c loops gcc optimization