1.3 寄存器
在 CPU 和内存之间交换数据是冯诺伊曼体系下计算的关键步骤之一。指令和操作数需要从内存被传输到 cpu 中。一些指令会把结果保存在内存中。两者速度的不对等导致了系统的瓶颈,CPU 时间在等待内存芯片响应数据时会被浪费。为了避免一直等待,处理器中被装入了自己的内存单元,叫作寄存器。寄存器的数量很少,速度很快。一般的程序大部分的时间都只是对一小拔数据进行处理。这个事实可以说明 CPU 大部分时间都是在操作寄存器。
寄存器是基于晶体管的,主存则是基于电容器的。我们倒是也可以用晶体管来实现主存来获取到速度很快的组件。不过还是有一些原因让工程师们没有这么做,而选择了其它的加速方式:
- 寄存器太贵了
- 机器指令中编码了寄存器的编号,如果要对更多的寄存器进行寻址,那指令的长度也会增大
- 寄存器增加了电路寻址的复杂度。更复杂的电路想加速也会变得更难。想要让一个很大的寄存器在 5 GHz 频率下工作不是一件容易的事情
如果根据常识来看,使用寄存器是会拖慢计算机的运行的。因为所有数据都要在计算前从内存取到寄存器,计算完了再 flush 回去,那寄存器到底带来了啥好处呢?
实际上我们编写的程序有一个特殊的属性,就是程序代码是由一般的程序模式,例如循环,函数,数据复用来组成,而不是一些自然规律。
这种特性叫作局部性,局部性具体在时间的局部性和空间的局部性。
时间局部性意思是对同一个地址的访问可能在很短的时间内还会发生 。
空间局部性是指我们在代码里访问了地址 X,那么很可能接着访问邻近 X 的那些地址,(例如 X-16 或 X+28)。
这两个特性也不是一定的,你可以写出强局部性或弱局部的代码。
不过典型的程序一般会用下面这种模式:数据集合很小而且可以被保存在寄存器中。当把数据取到寄存器中时,我们会反复地对其进行使用,之后再把结果 flush 到内存。内存中的数据很少被程序使用。一旦我们使用这些数据那么就会导致性能上的下降,原因是:
- 我们需要把数据取到寄存器中
- 如果所有的数据都被我们之后要使用的数据占用了,那我们只能先把一些内容临时存在内存单元中
■Note 一个广泛传播的场景:降低程序在最坏情况下的性能而提升平均性能。这种做法很多时候还是有效的,但在构建实时系统时则是被禁止的。实时系统对最差响应时间有严格的限制。这种系统规定在最差的情况下也要在限定的时间内响应,因此降低最坏情况下的情况在实时系统中是行不通的。