从极低级别编程的角度来看,如何执行两个数字之间的比较?
使用一个字节,写入无符号数字0,1和255:
0 -----> 00000000
1 -----> 00000001
255 ---> 11111111
现在,在比较这些数字时会发生什么?
使用我的视觉作为已经学习基本编程的人,我可以想象以下关于==
实现的算法:
b = 0
while b < 8:
if first_number[b] != second_number[b]:
return False
b += 1
return True
基本上这就像逐步比较每一位,如果两位不同,则在结束前停止。
因此我们注意到,比较在第一次迭代时停止,比较0和255,而如果比较0和1则停止在最后一次。
第一次比较比第二次比较快8倍。
在实践中,我怀疑是这样的。但这在理论上是否正确? 如果没有,计算机如何工作?
答案 0 :(得分:3)
整数之间的比较由cpu作为减法实现,其结果符号包含有关哪个数字更大的信息。
虽然减法的简单实现一次执行一个比特(因为每个比特都需要知道前一个比特的进位),但是典型实现使用进位超前电路,允许同时计算更多结果比特
所以,答案是:不,每次比较对于每一个可能的输入都需要几乎相同的时间。
答案 1 :(得分:2)
硬件与主流编程范例根本不同之处在于,所有逻辑门(或通常的电路)始终独立地并行地工作。没有&#34;做这个,然后做那个&#34;,只有&#34;在这里做这个,把结果送到那边的电路&#34;。如果芯片上有输入A和输出B的电路,那么电路总是连续地根据A的当前值更新B - 无论现在是否需要结果&#34;大图&#34;。
你的伪代码算法甚至没有开始很好地映射到逻辑门。相反,比较器在Verilog中看起来像这样(忽略那里有一个内置的==
运算符):
assign not_equal = (a[0] ^ b[0]) | (a[1] ^ b[1]) | ...;
每个XOR是一个独立的逻辑门,因此独立于其他逻辑门。结果减少了#34;使用逻辑或者,即如果任何XOR产生1,则输出为1(这也是一些并行工作,但关键路径长于一个门)。此外,无论特定的比特值如何,所有这些门都存在于硅中,并且对于w比特整数,信号必须传播通过大约(1 + log w)个门。这种传播延迟再次与中间和最终结果无关。
在某些CPU系列中,通过减去两个数字并将结果与零进行比较(使用上述电路)来实现相等比较,但同样的原则也适用。加法器/减法器不会变慢或变快,具体取决于值。
更不用说CPU中的指令无论如何都不会超过一个时钟周期,因此即使硬件完成得更快,下一条指令仍然无法启动直到下一个时钟周期。 / p>
现在,某些硬件操作可能需要不同的时间,但那是因为它们是状态机,即顺序逻辑。 技术上可以使用状态机实现算法的道德等价物,但是没有人这样做,它比上面的天真的,未优化的组合电路更难实现,并且效率更低引导。
状态机电路是带有存储器的电路:它们存储它们的当前状态并始终计算每个时钟周期的输出(取决于当前状态)和下一个状态(取决于当前状态和输入)。在某些输入上,它们可能会经历N个状态,直到它们产生输出,而N + x则在其他输入上。 ALU操作通常不会这样做。管道停顿,分支错误预测和缓存未命中是在某些情况下一条指令比平时花费更长时间的常见原因。以一种帮助程序员编写更快的代码的方式对这些进行正确推理是很困难的:你必须考虑到真正的硬件的所有棘手和怪癖,并且还有很多这些。经验证据,即对真正的黑匣子CPU进行基准测试,至关重要。
答案 2 :(得分:0)
当它到达程序集时,无论变量的内容如何,都会使用cmp
指令。
所以没有性能差异。