变量x
是一个整数,可能的取值为:-1、0、1、2、3
。哪个表达式在CPU时钟周期中更快:
1. (x < 0)
2. (x == -1)
语言:C/C++,但我认为所有其他语言都将是相同的。
P.S. 我个人认为答案是(x < 0)
。
对于高手们更广泛的问题:如果x
从-1
到2^30
怎么办?
变量x
是一个整数,可能的取值为:-1、0、1、2、3
。哪个表达式在CPU时钟周期中更快:
1. (x < 0)
2. (x == -1)
语言:C/C++,但我认为所有其他语言都将是相同的。
P.S. 我个人认为答案是(x < 0)
。
对于高手们更广泛的问题:如果x
从-1
到2^30
怎么办?
这完全取决于你所编译的ISA以及编译器优化器的质量。不要过早地优化:首先进行性能分析,找出瓶颈。
尽管如此,在x86中,你会发现在大多数情况下两者的速度都是一样快的。无论哪种情况,你都会有一个比较指令(cmp
)和一个条件跳转指令(jCC
)。然而,对于(x < 0)
,在某些情况下编译器可以省略cmp
指令,从而使你的代码加速一个完整周期。
具体来说,如果值x
存储在寄存器中,并且最近是一次算术运算(例如add
或sub
,但还有许多其他可能性)的结果,该运算设置了EFLAGS寄存器中的符号标志SF,那么就不需要cmp
指令,编译器可以只发出一个js
指令。没有简单的jCC
指令可以在输入为-1时跳转。
尝试一下并观察结果!每个测试分别做100万次或者甚至10亿次,并计时。我敢打赌你的结果没有统计学意义,但谁知道呢——也许在你的平台和编译器上,你可能会得到一个结果。
这是一个很棒的实验,让你相信过早优化可能不值得你花费时间——并且很可能是“所有邪恶的根源——至少在编程中是如此"。
这两种操作都可以在单个CPU步骤中完成,因此它们在性能上应该是相同的。
x < 0会更快。如果没有其他原因,它可以防止将常量-1作为操作数获取。 大多数架构都有针对与零进行比较的特殊指令,这也有所帮助。
这可能取决于比较操作之前或之后的操作。例如,如果在进行比较之前刚刚给x赋值,那么检查符号标志可能比与特定值进行比较更快。或者CPU的分支预测性能可能会受到所选择比较的影响。
但是,正如其他人所说,这取决于CPU架构、内存架构、编译器和许多其他因素,因此没有通用答案。
如果没有上下文,你甚至无法回答这个问题。如果你试图进行微不足道的微基准测试,优化器完全有可能会将你的代码飘到虚空中:
// 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.
Nikolay,你写道:
实际上,在高负载程序中是瓶颈运算符。在这1-2个字符串中,性能比可读性更有价值...
所有的瓶颈通常都很小,即使在完美的设计和完美的算法中也是如此(虽然不存在这样的算法)。我进行高负载DNA处理,并且非常了解我的领域和算法。
如果是这样,为什么不这样做:
您将得到答案。
同样,这两个操作通常在一个时钟周期内完成。
这取决于架构,但 x == -1 更容易出错。x < 0 是更好的选择。