我一直想知道为什么处理器在32个寄存器处停止。它是迄今为止最快的机器,为什么不仅仅用更多的寄存器来制造更大的处理器呢?这是否意味着减少对RAM的访问?
我一直想知道为什么处理器在32个寄存器处停止。它是迄今为止最快的机器,为什么不仅仅用更多的寄存器来制造更大的处理器呢?这是否意味着减少对RAM的访问?
Answers:
首先,并非所有处理器架构都在32个寄存器处停止。几乎所有在指令集中公开了32个寄存器的RISC体系结构实际上都具有32个整数寄存器和32个更多的浮点寄存器(因此64个)。(浮点“加”使用的寄存器与整数“加”使用的寄存器不同。)SPARC体系结构具有寄存器窗口。在SPARC上,一次只能访问32个整数寄存器,但这些寄存器的作用就像堆栈一样,您一次只能压入和弹出16个新寄存器。HP / Intel的Itanium体系结构在指令集中公开了128个整数和128个浮点寄存器。NVidia,AMD,Intel,ARM和Imagination Technologies的现代GPU都在其寄存器文件中公开了大量寄存器。(我知道这对于NVidia和Intel体系结构是正确的,我对AMD,ARM和Imagination指令集不是很熟悉,但是我认为寄存器文件也很大。)
其次,大多数现代微处理器都实现了寄存器重命名,以消除由于需要重用资源而引起的不必要的序列化,因此基础物理寄存器文件可以更大(某些计算机上为96、128或192个寄存器。)(动态调度)消除了一些编译器需要生成这么多唯一的寄存器名称,同时仍然为调度程序提供更大的寄存器文件。
有两个原因可能导致难以进一步增加指令集中公开的寄存器数量。首先,您需要能够在每条指令中指定寄存器标识符。32个寄存器需要一个5位的寄存器说明符,因此3地址指令(在RISC体系结构中很常见)仅花费32个指令位中的15个来指定寄存器。如果将其增加到6或7位,则可以减少指定操作码和常量的空间。GPU和安腾有很多大的指令。较大的指令需要付出一定的代价:您需要使用更多的指令存储器,因此指令缓存行为不太理想。
第二个原因是访问时间。内存越大,从中访问数据的速度就越慢。(就基本物理而言:数据存储在二维空间中,因此,如果要存储位,则到特定位的平均距离为。)寄存器文件只是一个较小的多端口内存,而使其变大的限制之一是,最终您将需要开始为计算机提供较慢的时钟,以容纳较大的寄存器文件。通常就整体性能而言,这是一个损失。
限制寄存器数量的另外两个原因:
许多代码具有大量的内存访问(典型值是30%)。其中,通常约2/3位是读访问,而1/3位是写访问。这不是由于用尽寄存器而不是访问数组,访问对象成员变量等引起的。
由于C / C ++的制作方式,必须在内存(或数据高速缓存)中完成此操作(您可以获得的所有指针都需要有一个地址,该地址必须潜在地存储在内存中)。如果编译器可以猜测您不会使用疯狂的间接指针技巧来写入变量willy-nilly,则会将其放入寄存器中,这对函数变量很有用,但不适用于全局可访问变量(通常,所有来自malloc的变量) ()),因为基本上不可能猜测全局状态将如何变化。
因此,编译器无论如何都不能使用大约16个以上的通用寄存器来执行任何操作,这并不常见。这就是为什么所有流行的架构都拥有这么多架构的原因(ARM有16种架构)。
MIPS和其他RISC往往有32个寄存器,因为拥有这么多寄存器并不是很困难-成本足够低,所以有点“为什么不?”。超过32个几乎是无用的,并且不利之处在于使寄存器文件的访问时间更长(每次寄存器数量加倍都可能会增加多路复用器的额外层,从而增加更多的延迟...)。平均而言,这还会使指令稍长一些-这意味着,当运行取决于指令内存带宽的程序时,实际上额外的寄存器会减慢您的速度!
如果您的cpu是有序的,并且没有进行寄存器重命名,并且您试图每个周期执行很多操作(超过3个),那么理论上您需要更多的寄存器,因为每个周期的ops数量会增加。这就是Itanium具有如此多寄存器的原因!但是在实践中,除了数字浮点或面向SIMD的代码(Itanium确实擅长)之外,大多数代码将具有大量的内存读/写和跳转,这使每个周期实现3个以上ops的梦想成为不可能(尤其是在面向服务器的软件(如数据库,编译器,高级语言执行(如javascript,仿真等)中))。这就是使Itanium沉没的原因。
归结为计算与执行之间的差异!
谁告诉您处理器总是有32个寄存器?x86有8个,ARM 32位,x86_64有16个,IA-64有128个,还有其他许多数字。你可以在这里看看。即使是MIPS,PPC或任何在指令集中具有32个通用寄存器的体系结构,其数量也远大于32,因为始终仍然存在标志寄存器(如果有),控制寄存器...不包括重命名的寄存器和硬件寄存器
一切都有其代价。寄存器的数量越大,执行任务切换时您要做的工作越多,指令编码中需要的空间就越大。如果您的寄存器较少,则在某些功能强大的代码中缺乏寄存器的权衡下,在从函数调用和返回任务或切换任务时不必存储和恢复大量内容
而且,寄存器文件越大,它将越昂贵和复杂。SRAM是最快,最昂贵的RAM,因此仅用于CPU高速缓存。但是与具有相同容量的寄存器文件相比,它仍然便宜得多并且占用的空间更少。
例如,典型的英特尔处理器具有“官方”的16个整数和16个矢量寄存器。但实际上,还有更多:处理器使用“寄存器重命名”。如果您有一条指令reg3 = reg1 + reg2,那么如果使用reg3的另一条指令尚未完成,您将遇到问题-您无法执行新指令,以防新指令覆盖reg3之前被前一条指令读取。
因此,大约有160个左右的实际寄存器。因此,上面的简单指令更改为“ regX = reg1 + reg2,并记住regX包含reg3”。没有重命名寄存器,乱序执行将完全陷入水中。
我不是电气工程师,但是我认为限制寄存器数量的另一种可能是路由。算术单元数量有限,并且它们必须能够从每个寄存器获取输入,并输出到每个寄存器。当您拥有可以在每个周期执行许多指令的流水线程序时,尤其如此。
一个简单的版本将具有复杂度,使得无法扩展的寄存器数量成为可能,或者以其他方式需要重新设计路由,使其复杂得多,从而以更高的复杂度路由所有内容。
通过观看Ivan Godard关于Mill CPU的一些演讲,我得到了这个答案的主意。Mill CPU的部分创新之处在于,您不能输出到任意寄存器-输出都被压入寄存器堆栈或“皮带”,从而减少了布线问题,因为您始终知道输出将到达何处。注意,它们仍然存在将输入寄存器传送到算术单元的路由问题。
有关问题说明,请参见Mill CPU体系结构-传送带(9之2),以及Mill的解决方案。