变量x
是具有可能值的 int -1, 0, 1, 2, 3
:。哪个表达式会更快(在 CPU 滴答声中):
1. (x < 0)
2. (x == -1)
语言:C/C++,但我想所有其他语言都一样。
PS我个人认为答案是(x < 0)
。
对大师来说更广泛:如果x
从-1
到2^30
怎么办?
变量x
是具有可能值的 int -1, 0, 1, 2, 3
:。哪个表达式会更快(在 CPU 滴答声中):
1. (x < 0)
2. (x == -1)
语言:C/C++,但我想所有其他语言都一样。
PS我个人认为答案是(x < 0)
。
对大师来说更广泛:如果x
从-1
到2^30
怎么办?
这完全取决于您正在为其编译的 ISA,以及编译器优化器的质量。不要过早地优化:首先分析以找到您的瓶颈。
也就是说,在 x86 中,您会发现在大多数情况下两者都同样快。在这两种情况下,您都会有比较 ( cmp
) 和条件跳转 ( jCC
) 指令。但是,对于(x < 0)
某些情况,编译器可能会省略cmp
指令,从而将您的代码加速一个完整的周期。
具体来说,如果该值x
存储在寄存器中,并且是最近在 EFLAGS 寄存器中设置符号标志 SF 的算术运算(例如add
、 或sub
,但还有更多可能性)的结果,则不需要该cmp
指令,编译器只能发出一条js
指令。当输入为 -1 时,没有简单的jCC
指令会跳转。
试试看!做一百万,或者更好,每个十亿,然后计时。我敢打赌,您的结果没有统计意义,但谁知道——也许在您的平台和编译器上,您可能会找到结果。
这是一个很好的实验,可以让自己相信过早的优化可能不值得你花时间——而且很可能是“万恶之源——至少在编程中”。
这两个操作都可以在一个 CPU 步骤中完成,因此它们的性能应该相同。
x < 0 会更快。如果没有别的,它会阻止获取常量 -1 作为操作数。大多数架构都有与零进行比较的特殊说明,因此这也会有所帮助。
它可能取决于比较之前或之后的操作。例如,如果您在进行比较之前为 x 分配了一个值,那么检查符号标志可能比与特定值进行比较更快。或者 CPU 的分支预测性能可能会受到您选择的比较的影响。
但是,正如其他人所说,这取决于 CPU 架构、内存架构、编译器和许多其他东西,所以没有一般的答案。
无论如何,重要的考虑因素是哪个实际上可以准确地指导您的程序流程,而哪个恰好产生相同的结果?
如果 x 实际上是索引或枚举中的值,那么 -1 将始终是您想要的,或者任何负值都有效?目前,-1 是唯一的负面因素,但这可能会改变。
你甚至不能断章取义地回答这个问题。如果您尝试一个微不足道的微基准测试,优化器完全有可能将您的代码飘入以太:
// Get time
int x = -1;
for (int i = 0; i < ONE_JILLION; i++) {
int dummy = (x < 0); // Poof! Dummy is ignored.
}
// Compute time difference - in the presence of good optimization
// expect this time difference to be close to useless.
同样,这两个操作通常在 1 个时钟内完成。
这取决于架构,但 x == -1 更容易出错。x < 0 是要走的路。
正如其他人所说,可能没有任何区别。比较是 CPU 中的基本操作,芯片设计人员希望尽可能快地进行比较。
但是您可以考虑其他一些事情。分析每个值的频率并按该顺序进行比较。这可以为您节省不少周期。当然,您仍然需要将代码编译为 asm 来验证这一点。
我相信你相信这是一个真正的耗时。
我想问机器会给出比我们任何人都更可靠的答案。
我发现,即使在你所说的代码中,我的假设也不是很正确。例如,如果这是在一个内部循环中,如果有任何类型的函数调用,即使是编译器插入的不可见的,该调用的成本将占主导地位。
尼古拉,你写道:
它实际上是高负载程序中的瓶颈算子。这 1-2 个字符串的性能比可读性更有价值......
所有的瓶颈通常都这么小,即使在完美的设计和完美的算法中(尽管没有这样的)。我进行高负荷 DNA 处理,并且非常了解我的领域和算法
如果是这样,为什么不做下一步:
你会得到答案。