我偶然发现this question/answer提到了大多数语言中的逻辑运算符,例如:
x == y && doSomething();
可能比使用if
分支做同样的事情更快:
if(x == y) {
doSomething();
}
同样,它说三元运算符:
x = y == z ? 0 : 1
通常比使用if
分支更快:
if(y == z) {
x = 0;
} else {
x = 1;
}
这让我得到了谷歌搜索,这导致我this fantastic answer解释了分支预测。
基本上,它所说的是CPU以非常快的速度运行,而不是减速以计算每个if
分支,它试图猜测将发生什么结果并将适当的指令放在其管道中。但如果它做出了错误的猜测,就必须备份并重新计算相应的指令。
但是这仍然没有向我解释为什么逻辑运算符或三元运算符的处理方式与if
分支不同。由于CPU不知道x == y
的结果,不应该猜测是否要将调用发送到doSomething()
(因此,doSomething
全部(#)代码)进入其管道?因此,如果猜测不正确,请备份吗?类似地,对于三元运算符,在确定y == z
中要存储的内容时,CPU是否不得不猜测x
是否会评估为真,如果猜测错误则需要备份?
我不明白为什么编译器对分支的处理方式与有条件的任何其他语句的处理方式不同。不应该以同样的方式评估所有条件吗?
答案 0 :(得分:3)
简短的回答 - 它根本就不是。虽然帮助分支预测可以提高性能 - 使用它作为一个部分,逻辑语句不会改变编译的代码。 如果你想帮助分支预测使用__builtin_expect(对于GNU)
要强调让我们比较编译器输出:
#include <stdio.h>
int main(){
int foo;
scanf("%d", &foo); /*Needed to eliminate optimizations*/
#ifdef IF
if (foo)
printf("Foo!");
#else
foo && printf("Foo!");
#endif
return 0;
}
对于gcc -O3 branch.c -DIF 我们得到:
0000000000400540 <main>:
400540: 48 83 ec 18 sub $0x18,%rsp
400544: 31 c0 xor %eax,%eax
400546: bf 68 06 40 00 mov $0x400668,%edi
40054b: 48 8d 74 24 0c lea 0xc(%rsp),%rsi
400550: e8 e3 fe ff ff callq 400438 <__isoc99_scanf@plt>
400555: 8b 44 24 0c mov 0xc(%rsp),%eax
400559: 85 c0 test %eax,%eax #This is the relevant part
40055b: 74 0c je 400569 <main+0x29>
40055d: bf 6b 06 40 00 mov $0x40066b,%edi
400562: 31 c0 xor %eax,%eax
400564: e8 af fe ff ff callq 400418 <printf@plt>
400569: 31 c0 xor %eax,%eax
40056b: 48 83 c4 18 add $0x18,%rsp
40056f: c3 retq
对于gcc -O3 branch.c
0000000000400540 <main>:
400540: 48 83 ec 18 sub $0x18,%rsp
400544: 31 c0 xor %eax,%eax
400546: bf 68 06 40 00 mov $0x400668,%edi
40054b: 48 8d 74 24 0c lea 0xc(%rsp),%rsi
400550: e8 e3 fe ff ff callq 400438 <__isoc99_scanf@plt>
400555: 8b 44 24 0c mov 0xc(%rsp),%eax
400559: 85 c0 test %eax,%eax
40055b: 74 0c je 400569 <main+0x29>
40055d: bf 6b 06 40 00 mov $0x40066b,%edi
400562: 31 c0 xor %eax,%eax
400564: e8 af fe ff ff callq 400418 <printf@plt>
400569: 31 c0 xor %eax,%eax
40056b: 48 83 c4 18 add $0x18,%rsp
40056f: c3 retq
这是完全相同的代码。
您与JAVAScript的衡量绩效相关联的问题。请注意,它可以被解释(因为Java脚本被解释或JIT取决于版本)到两种情况不同的东西。 无论如何,JavaScript并不是学习性能的最佳选择。