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))上,所有指令都是有条件的。有时,尽管有多个条件,但您可以摆脱具有单个分支(从结束到开始)的内部循环。在一些逻辑比较(
相反,iirc(我从未对其进行过实际的编程,但在十多年前已经研究过C编译器的输出)68000只有寄存器d4有一个文字eor/xor指令。因此,算术比较可能会更好(尽管您仍然可以忽略无关的标志——重点是指令集有点不规则)。
正如前面的海报所提到的,大多数操作都会随着内存、磁盘、网络和Web服务的延迟而提高。
比较操作发生在微处理器时钟信号的上升(或下降)边缘。然后下一个操作在下一个时钟周期发生。因此,就执行速度而言,现在市场上几乎每一个处理器所花的时间都是相同的,即平等和不平等。
我之所以这么说,几乎是因为我记得读过一些处理器,它们本不应该是基于时钟的,而是基于操作时间的,所以如果比较操作确实比加法操作快,那么一组n比较比n加法花费的时间要短。但99%的人认为这只是一个研究项目,而不是商业产品:)
每个人都假设的一个方面是他在谈论寄存器级指令。每个人都是对的,基本上在CPU层面上是没有意义的。甚至更高一级的操作都会写下不等式,称之为对等式的否定。
然而,更高的是,使用发问者的优化可以双向工作。这就是平等可以像不平等一样有效地书写。
此外,对于与装配操作有关的人员来说,CMP和SUB之间的唯一区别是设置了哪些标志。它们通常使用机器的相同部分执行,因为CMP必须返回表示等于、小于和大于的标志。
像这样进行比较所需的时间通常是一个时钟周期。
32位处理器将同时处理所有32位;64位处理器将同时处理64位。
如果管道中存在延迟或暂停,则可能是因为操作数不可用且必须获取。这就是开销最大的地方。但这将在一个适合处理器体系结构的块中完成,因此它仍然会作为32位或64位单元被拉入。