C++ 帮助编译器优化branchy代码序列
我有C/C++中的代码序列,其中包含许多 分支,类似这样的:C++ 帮助编译器优化branchy代码序列,c++,c,optimization,C++,C,Optimization,我有C/C++中的代码序列,其中包含许多 分支,类似这样的: if( condition1 ) return true; if( condition2 ) return true; ... return false; (相当于返回条件1 | |条件2 | |…) 评估每个条件都需要多次内存访问(均为只读),但编译器在评估前一个条件之前不移动内存访问,从而错过了重要的优化机会。原因是当condition1为true时,condition2的内存访问可能会出错。 我知道他们没有,我
if( condition1 )
return true;
if( condition2 )
return true;
...
return false;
(相当于返回条件1 | |条件2 | |…)
评估每个条件都需要多次内存访问(均为只读),但编译器在评估前一个条件之前不移动内存访问,从而错过了重要的优化机会。原因是当condition1为true时,condition2的内存访问可能会出错。
我知道他们没有,我希望编译器做一些明智的事情,在适合性能的地方混合一些代码序列,例如利用指令级并行性。
我也不想将条件更改为逻辑or(而不是短路),因为其中一个分支可能会跳出
关于如何实现这一点有什么想法(最好使用gcc)
谢谢
评估每个条件都需要多次内存访问
为什么不在个别情况下避免短路评估,但在其他情况下让短路评估发生
对内置类型使用不短路的运算符
具体实现前者的方式取决于这些条件的性质(即代码中的condition1
,condition2
)——如果您没有说明它们,我只能笼统地说:它们内部包含短路运算符,相反,将布尔值转换为整数表示形式,并使用例如按位或(如果它读起来更好并且在您的特定用法中工作,甚至使用“+”或“*”)。位运算符通常更安全,因为它们的优先级较低-只有在您的条件已经包含位运算符时才需要小心
举例说明:
OLD: return (a > 4 && b == 2 && c < a) || // condition1
(a == 3 && b != 2 && c == -a); // condition2
NEW: return (a > 4 & b == 2 & c < a) ||
(a == 3 & b != 2 & c == -a);
您可能还希望使用
bool condition1 = a > 4 & b == 2 & c < a;
bool condition2 = a == 3 & b != 2 & c == -a;
return condition1 || condition2;
bool条件1=a>4&b==2&c
…这可能更快-可能仅在整体“return false”情况下,并且可能在最后一两个条件n是“return true”的决定因素时
用户定义的操作员可避免短路评估
另外,对于具有重载逻辑运算符的对象禁用短路求值,这为您使用现有符号进行检查提供了另一种途径,但您必须更改或增强数据类型
思想
更一般地说,只有在每个条件中组合了大量断言时,您才能从中受益——如果函数倾向于运行到返回false,则更是如此
“APProgrammer”也提出了一个很好的观点——由于在现代CPU上可以进行推测性执行,CPU可能已经领先于短路评估所暗示的顺序(在某些特殊模式下,可以避免或抑制任何内存故障,从而取消对无效指针的引用、除以0等)。因此,整个优化尝试可能被证明毫无意义,甚至适得其反。需要对所有备选方案进行基准测试。您能自己移动部分条件吗 即
constboolbcondition1result=;
常量布尔b条件2result=;
等等
为了更好的优化仍然。。。重新调整条件的顺序,以便首先检查命中率最高的条件。通过这种方式,它将更经常地提前退出(这可能没有什么区别)。看看gcc提供的函数。当我们像linux内核那样定义宏时,这些宏可以直观地使用,对代码可读性几乎没有影响。不用麻烦了。CPU已经有无序执行、推测执行和分支预测。这一级别的任何差异都不太可能产生任何影响。指令级并行是由CPU隐式完成的,而不是由编译器显式完成的。也许GCC什么也没做,因为没有什么可以得到的 在这一点上,您必须有一个地狱般的条件来改变一个非平凡应用程序的运行时间
哦,逻辑or是保证短路的标准。也许我在这里误解了什么,但是如果(条件2),如果你不想在条件1为真的情况下对其进行评估,为什么不直接使用
else呢?@reko\u t:不会改变任何东西,return
已经保证了这一点@PoweRoy:大胆的评论,这可能会使情况恶化(OO抽象并不意味着提高性能),你有事实支持吗?@PoweRoy:这会有什么帮助,确切地说?@GMan:嘿,我喜欢OOP,适度;)但在寻找性能时,这很少是一个好的答案。考虑到推测性执行的存在,我不太确定编译器是否遗漏了一些东西。你能更明确地说明条件之间的关系吗,举个例子。+1:像这样单独评估每个条件会引起条件n术语之间(但不在条件n术语内)的并行性,尽管如果优化者没有真正参与其中,它可能会导致对所有条件项的评估,即使早期的条件项足以确定函数的返回值。如果hans能给出反馈,他会很感兴趣的。
bool condition1 = a > 4 & b == 2 & c < a;
bool condition2 = a == 3 & b != 2 & c == -a;
return condition1 || condition2;
const bool bCondition1Result = <condition1>;
const bool bCondition2Result = <condition2>;