Algorithm 重写if语句以避免分支是否值得?
最近,我意识到我做了太多分支,而不关心它对性能的负面影响,因此我决定尝试学习所有关于不分支的知识。这里有一个更极端的例子,试图使代码具有尽可能少的分支 因此,对于代码Algorithm 重写if语句以避免分支是否值得?,algorithm,branch,Algorithm,Branch,最近,我意识到我做了太多分支,而不关心它对性能的负面影响,因此我决定尝试学习所有关于不分支的知识。这里有一个更极端的例子,试图使代码具有尽可能少的分支 因此,对于代码 if(expression) A = C; //A and C have to be the same type here obviously 表达式可以是A==B,或Q取决于编译器、指令集、优化器等。当使用布尔表达式作为int值时,例如(A==B)*C,编译器必须进行比较,并根据结果将一些寄存器设置为0或1。
if(expression)
A = C; //A and C have to be the same type here obviously
表达式可以是A==B,或Q取决于编译器、指令集、优化器等。当使用布尔表达式作为
int
值时,例如(A==B)*C
,编译器必须进行比较,并根据结果将一些寄存器设置为0或1。有些指令集除了分支之外可能没有其他方法来实现这一点。一般来说,最好编写简单、直接的代码,让优化器来解决,或者找到一个分支较少的不同算法。天哪,不,不要这样做强>
任何“因为分支而惩罚你很多”的人都希望你因为使用了如此糟糕的东西而被解雇
这有多可怕,让我来数一数:
C
)乘以一个布尔值(例如,(a==B)
产生true
或false
)。有些语言会,有些不会<>你只应该考虑如果你已经分析了程序的运行时属性,并确定这里有一个频繁的分支错误预测,这就造成了实际的性能问题。它使代码变得不那么清晰,而且一般来说它的速度并不明显(在您感兴趣的情况下,这也是您必须测量的)。在进行研究后,我得出结论,当出现瓶颈时,最好包括定时分析器,因为这类代码通常不可移植,主要用于优化 我在阅读了下面的问题后得到了一个确切的例子
我用C++测试了我的代码,因为额外的算术,我的实现实际上是慢的。 然而! 对于下面的这种情况
if(expression) //branched version
A += C;
//OR
A += (expression)*(C); //non-branching version
时间就是这样。
分支排序列表大约需要2秒钟
分支未排序列表约为10秒
我的实现(无论是排序的还是未排序的)都是3秒
这表明,在一个未排序的瓶颈区域,当我们有一个简单的分支,可以简单地用一次乘法代替时
考虑我所提出的实施方案可能更有价值。
**同样,它主要是针对被视为瓶颈的区域**这里应该是什么类型的A、B和C?你能用一个布尔值乘以C吗?为此,假设它们都是整数。谢谢首先,您应该更仔细地考虑代码的结构,以查看条件是否可以简化,因为每个条件块都是您必须结合其他块进行测试的另一条路径。之后,对于简单的情况,您应该首先检查是否有编译器开关(例如,GCC中的
-mcpu
,-mtune
),这将鼓励编译器自动执行此操作。如果您必须手工编写一个无分支条件的代码,那么最好使用a^=-(a==B)和(C^B)代码>,但您仍然希望编译器在内部对a==B
进行无分支计算。当然,您可以将其分解为a+=(a==B)*(C-a)
?哦,感谢您的改进!但是,有些编译器并不一定擅长这些优化。无论您想要分支代码还是HACKY代码,都要看您需要多少性能和代码如何使用。值得注意的是,这主要是我在VisualStudio环境下对C++进行测试后得出的结论。因此,在进行此类优化时,应始终使用定时探查器
if(expression) //branched version
A += C;
//OR
A += (expression)*(C); //non-branching version