关于优化:不等式运算符比等式运算符更快吗?

Is the inequality operator faster than the equality operator?

我知道这是一个微观的优化,所以我出于好奇问。

从逻辑上讲,微处理器不需要比较相等运算符的两个操作数的所有位来确定"假"结果。

注意,这与编程有关,因为它会影响程序的执行速度。


通常,微处理器使用电子门进行比较,而不是像那样一步一步地进行比较。它一次检查所有位。


这取决于您的平台,但一般来说,它的性能是相同的。

例如,在x86上,您可以通过查看程序集的工作方式看到这一点。查看x86程序集控制流操作-无论您是在执行相等还是不相等操作,它都是作为2个操作完成的。

首先,执行CMP(比较)操作。然后检查比较是否相等,不相等,等等。这只是检查比较的结果-在这两种情况下,您都要执行两个操作。

然而,在许多高级编程语言中,情况是不同的。许多语言都用平等来定义不平等——要检查不平等,需要进行平等检查,然后再进行第二次检查,看看是否是错误的。这使得这些语言在微观上的平等速度更快。许多语言也允许你具体地写这两种语言——但是许多人倾向于用平等来写不平等,这同样使平等,一般来说,稍微快一点。


听起来您应该阅读《英特尔64和IA-32体系结构优化参考手册》。

在这里查找您使用的指令上的"管道延迟"和"管道延迟"。只要说你用ints做的每件事都需要大约1个时钟周期来执行(每秒40亿个)。从内存中读取数据可能需要100-1000,这取决于您使用的数据量。更重要的是。


比较通常是作为忽略结果的减法来实现的。CPU中的加法器将同时操作所有的位,所以这是一个恒定的时间操作。

相等就是确定输出是否为0。在x86上,有作为比较结果设置的标志,分支是通过JZ或JNZ完成的(如果为零,则跳转,如果不是零)。所以,不会有真正的速度差。

其他平台(如ARM和IA64)的行为类似。


指令本身将以与其他答案建议的相同速度执行。

可能会遇到不同之处的地方是分支预测或缓存效果。这将因处理器和编译器的不同而不同,因此不可能进行归纳。如果你处在这样一个水平上,这会产生影响,唯一的方法就是尝试和测量。


如果你想把这个问题提到一个更一般的问题上,你就必须考虑正确和错误答案的合理分布,并且你必须考虑任意的字长,包括比寄存器长的字长。

在搜索算法中(排序可以被视为搜索的扩展),使用"<"或"<="等运算符比"=="更常见。这是因为"=="运算符的结果分布趋向于高度偏向于"假",因此每次执行都具有较低的熵(即低的信息产量)。这意味着它们必须执行更多次才能获得相同的信息-见证线性搜索。

在这两种情况下,它们都采用O(字长)位数的比较,但是,如果字长<=寄存器长度,则比较是并行进行的,可能会有少量的进位延迟。(实际上,正如我所想的,在典型的不相等情况下,两种比较都可以在第一个不相等的位上停止,如果相等的概率足够小,这可能很早就发生了。)


有一些小的案例可能会产生一些影响。

在ARM处理器(对于32位/非拇指指令集体系结构(ISA))上,所有指令都是有条件的。有时,尽管有多个条件,但您可以摆脱具有单个分支(从结束到开始)的内部循环。在一些逻辑比较(TEQ的情况下,干扰少数标志(影响负(n)和零(z),但不影响进位(c)或溢出(v)),允许有毛的代码避免分支指令(untaken)。

相反,iirc(我从未对其进行过实际的编程,但在十多年前已经研究过C编译器的输出)68000只有寄存器d4有一个文字eor/xor指令。因此,算术比较可能会更好(尽管您仍然可以忽略无关的标志——重点是指令集有点不规则)。

正如前面的海报所提到的,大多数操作都会随着内存、磁盘、网络和Web服务的延迟而提高。


比较操作发生在微处理器时钟信号的上升(或下降)边缘。然后下一个操作在下一个时钟周期发生。因此,就执行速度而言,现在市场上几乎每一个处理器所花的时间都是相同的,即平等和不平等。

我之所以这么说,几乎是因为我记得读过一些处理器,它们本不应该是基于时钟的,而是基于操作时间的,所以如果比较操作确实比加法操作快,那么一组n比较比n加法花费的时间要短。但99%的人认为这只是一个研究项目,而不是商业产品:)


每个人都假设的一个方面是他在谈论寄存器级指令。每个人都是对的,基本上在CPU层面上是没有意义的。甚至更高一级的操作都会写下不等式,称之为对等式的否定。

然而,更高的是,使用发问者的优化可以双向工作。这就是平等可以像不平等一样有效地书写。

此外,对于与装配操作有关的人员来说,CMP和SUB之间的唯一区别是设置了哪些标志。它们通常使用机器的相同部分执行,因为CMP必须返回表示等于、小于和大于的标志。


像这样进行比较所需的时间通常是一个时钟周期。

32位处理器将同时处理所有32位;64位处理器将同时处理64位。

如果管道中存在延迟或暂停,则可能是因为操作数不可用且必须获取。这就是开销最大的地方。但这将在一个适合处理器体系结构的块中完成,因此它仍然会作为32位或64位单元被拉入。