ldo*_*dog 5 c++ optimization loops
我有以下情况
bool user_set_flag;
getFlagFromUser(&user_set_flag);
while(1){
if(user_set_flag){
//do some computation and output
}
//do other computation
}
Run Code Online (Sandbox Code Playgroud)
该变量user_set_flag仅在代码中设置一次且仅一次,在开始时,其本质上是用户选择他想对程序执行的操作.假设用户选择user_set_flag = false然后编译器将以这样的方式编译代码,使得该if(user_set_flag)语句仅被检查一次,或者将始终被检查.我可以给编译器提示如将bool设置为const吗?
我问这个的原因是因为我的应用程序是时间关键的,它尽可能快地处理帧.一个总是错误的分支应该能够在运行时以某种方式确定?
int*_*nt3 14
首先,处理器具有称为分支预测的能力.经过几次循环后,处理器将能够注意到您的if语句始终是单向的.(它甚至可以注意到常规模式,例如true false true false.)然后它会推测性地执行该分支,只要它能够正确预测,if语句的额外成本就会大大消除.如果您认为用户更可能选择true而不是false,您甚至可以告诉gcc编译器(特定于gcc的扩展名).
但是,你在一条评论中提到你有一个"更复杂的bool序列".我认为处理器可能没有内存来模式匹配所有跳转 - 当它返回到第一个if语句时,知道跳转的方式已从其内存中移位.但我们可以帮助它...
编译器能够将循环和if语句转换为它认为更优化的形式.例如,它可能会将您的代码转换为schnaader给出的形式.这称为循环非开关.您可以通过执行配置文件引导优化(PGO)来帮助它,让编译器知道热点的位置.(注意:在gcc中,-funswitch-loops仅在打开时-O3.)
您应该在指令级别(VTune将是一个很好的工具)分析您的代码,以查看if语句是否真的是瓶颈.如果它们确实存在,并且通过查看生成的程序集,您认为尽管PGO编译器已经错了,您可以尝试自己提升if语句.也许模板化的代码会使它更方便:
template<bool B> void innerLoop() {
for (int i=0; i<10000; i++) {
if (B) {
// some stuff..
} else {
// some other stuff..
}
}
}
if (user_set_flag) innerLoop<true>();
else innerLoop<false>();
Run Code Online (Sandbox Code Playgroud)
我认为根本不可能进一步优化这一点.编译器足够聪明,知道user_set_flag在执行循环期间值不会改变,并将为此生成最有效的机器代码.
这也是二次猜测编译器的一些方面.除非你真的真的知道自己在做什么,否则最好坚持使用最简单的解决方案.
作为练习尝试使用if (true)和 来分析(时间)执行if(user_set_flag).我的猜测是执行时间差异不大.
另一种选择是:
if(user_set_flag){
while(1){
ComputationAndOutput();
OtherComputation();
}
} else {
while(1){
OtherComputation();
}
}
Run Code Online (Sandbox Code Playgroud)
但正如Smashery所说,这是微优化,并不会像你可以肯定的其他优化一样加速你的程序.