为什么英特尔将内部RISC内核隐藏在其处理器中?


89

从Pentium Pro(P6微体系结构)开始,英特尔重新设计了其微处理器,并根据旧的CISC指令使用了内部RISC内核。从Pentium Pro开始,所有CISC指令都被划分为较小的部分,然后由RISC内核执行。

一开始,对我来说很明显,英特尔决定隐藏新的内部架构,并迫使程序员使用“ CISC shell”。由于这一决定,英特尔可以完全重新设计微处理器架构而不会破坏兼容性,这是合理的。

但是我不明白一件事,为什么英特尔仍然将内部RISC指令集隐藏了这么多年?他们为什么不让程序员像使用旧的x86 CISC指令集那样使用RISC指令?

如果Intel保持了向后兼容性这么长的时间(我们仍然在64位模式旁边拥有虚拟8086模式),为什么它们不允许我们编译程序,因此它们将绕过CISC指令并直接使用RISC内核?这将为自然放弃如今不推荐使用的x86指令集开辟一种自然的方式(这是Intel决定在内部使用RISC内核的主要原因,对吧?)。

看到新的Intel“ Core i”系列,我发现它们仅扩展了CISC指令集,添加了AVX,SSE4等。


1
请注意,某些x86 CPU的内部RISC指令集已公开
phuclv

Answers:


90

不,肯定不建议使用x86指令集。它一如既往地受欢迎。英特尔内部使用一组类似RISC的微指令的原因是因为它们可以得到更有效的处理。

因此,x86 CPU的工作原理是在前端有一个非常耐用的解码器,该解码器接受x86指令,并将它们转换为后端可以处理的优化内部格式。

关于将此格式公开给“外部”程序,有两点:

  • 这不是稳定的格式。英特尔可以在不同的CPU模型之间进行更改,以最适合特定的体系结构。这使他们可以最大程度地提高效率,并且如果他们必须为内部使用和外部使用确定固定,稳定的指令格式,那么将失去这一优势。
  • 这样做没有任何收获。在当今庞大,复杂的CPU的情况下,解码器仅占CPU的一小部分。必须解码x86指令会使情况变得更加复杂,但是CPU的其余部分不受影响,因此总的来说,几乎没有什么收获,尤其是因为为了执行“旧版”代码,x86前端仍然必须存在。因此,您甚至都不会保存x86前端上当前使用的晶体管。

这不是一个完美的安排,但是成本却很小,与设计支持两个完全不同的指令集的CPU相比,这是一个更好的选择。(在那种情况下,他们可能最终会发明第三套微操作供内部使用,只是因为可以对其进行自由调整以使其最适合CPU的内部架构)


1
好点。RISC是一个很好的核心体系结构,其中GOOD意味着运行速度快并且可以正确实现,而具有CISC架构历史的x86 ISA只是现在,它是具有悠久历史和丰富的二进制软件的指令集布局。 ,以及高效的存储和处理功能。它不是CISC外壳,而是行业事实上的标准ISA。
沃伦·P

2
@沃伦:最后一部分,我实际上并不这么认为。一个设计良好的CISC指令集是在存储方面更有效,是的,但是从我所看到的几个测试,“平均” x86指令是像4.3字节宽,这是比它通常会在RISC体系结构。x86经过多年随意设计和扩展,因此失去了很多存储效率。但是正如您所说,它的主要优势是历史和大量现有的二进制代码。
jalf

1
我并不是说这是“精心设计的CISC”,只是“巨大的历史”。GOOD部分是RISC芯片设计部分。
沃伦·P

2
@jalf-通过检查实际的二进制文件,x86中的指令大小平均每个大约3个字节。当然会有更长的说明,但是较小的说明在实际使用中往往占主导地位。
偷听

1
平均指令长度不能很好地衡量代码密度:典型代码中最常见的x86指令类型是加载和存储(只需将数据移动到可以处理的位置,然后再返回到内存,RISC处理器和CISC的½即可)。很多寄存器,所以不需要做太多的事情,而且一条指令可以做多少(臂指令可以做大约三件事)
ctrl-alt-delor

20

真正的答案很简单。

实施RISC处理器的主要因素是降低复杂性并提高速度。RISC的缺点是降低了指令密度,这意味着以RISC格式表示的相同代码比等效的CISC代码需要更多的指令。

如果您的CPU与内存以相同的速度运行,或者至少如果它们都以合理的相似速度运行,则这种副作用并不重要。

当前,与CPU速度相比,内存速度在时钟方面显示出很大差异。当前的CPU有时比主内存快五倍或更多。

这种技术状态倾向于使用更密集的代码,这是CISC提供的。

您可以说缓存可以加快RISC CPU的速度。但是关于CISC cpus也可以这样说。

与RISC和高速缓存相比,使用CISC和高速缓存可以获得更大的速度改进,因为相同大小的高速缓存对CISC提供的高密度代码的影响更大。

另一个副作用是RISC在编译器实现上更加困难。为CISC cpus优化编译器更加容易。等等

英特尔知道他们在做什么。

的确如此,ARM拥有一种称为Thumb的更高代码密度模式。


1
内部RISC内核也减少了CISC CPU上的晶体管数量。您可以使用微代码来执行它们,而不必硬性连接每条CISC指令。这导致针对不同的CISC指令重用RISC微代码指令,从而使用更少的管芯面积。

16

如果Intel保持了向后兼容性这么长的时间(我们仍然在64位模式旁边拥有虚拟8086模式),为什么它们不允许我们编译程序,因此它们将绕过CISC指令并直接使用RISC内核?这将为自然放弃如今不推荐使用的x86指令集开辟一种自然的方式(这是Intel决定在内部使用RISC内核的主要原因,对吧?)。

您需要从业务角度来看。英特尔实际上已经试图摆脱x86的影响,但这是为公司奠定金蛋的鹅。XScale和Itanium从未达到其核心x86业务所具有的成功水平。

您基本上要问的是,英特尔要张开手腕以换取开发人员的热情。破坏x86并不符合他们的利益。任何使更多开发人员不必选择针对x86的因素都会破坏x86。反过来,这破坏了他们。


6
是的,当英特尔尝试这样做(Itanium)时,市场只是耸耸肩回应。
沃伦·P

应当指出,Itanium出现故障时有多种因素,而不仅仅是因为它是一种新架构。例如,将CPU调度卸载到从未真正实现目标的编译器上。如果Itanium的速度是x86 CPU的10倍或100倍,那么它的销售将像热蛋糕一样。但这并没有更快。
Katastic Voyage,

5

答案很简单。英特尔不会为开发人员开发CPU !他们正在为做出购买决定的人们开发这些产品,顺便说一句,世界上每家公司都在这样做!

英特尔很久以前就做出了这样的承诺:(当然,在合理的范围内)它们的CPU将保持向后兼容。人们想知道,当他们购买新的基于Intel的计算机时,所有当前软件的运行方式都将与旧计算机完全相同。(尽管,希望更快!)

此外,英特尔确切知道了这一承诺的重要性,因为他们曾经试图采用不同的方式。了解多少人使用Itanium CPU?!?

您可能不喜欢它,但是决定保留x86的决定是使Intel成为全球最知名的企业名称之一!


2
我不同意英特尔处理器对开发人员不友好的说法。我已经对PowerPC和x86进行了多年编程,所以我相信CISC对程序员更友好。(我现在为Intel工作,但是在我被聘用之前就下定了决心。)
Jeff

1
@Jeff根本不是我的意图!问题是,为什么英特尔没有打开RISC指令集,以便开发人员可以使用它。我没有说什么约86为非开发商友好。我所说的是这样的决定并不是在开发人员的头脑中做出的,而是严格的业务决定。
地理

5

@jalf的回答涵盖了大多数原因,但是没有提及一个有趣的细节:内部类似RISC的内核并未设计为运行诸如ARM / PPC / MIPS之类的指令集。x86税不仅在耗电的解码器中支付,而且在整个内核中都有一定程度的支付。即,不仅是x86指令编码;这是每条带有奇怪语义的指令。

假设英特尔确实创建了一种操作模式,其中指令流不是x86,而是指令直接映射到uops。我们还假设每个CPU型号在此模式下都有自己的ISA,因此它们仍然可以在需要时自由更改内部结构,并使用最少数量的晶体管来暴露它们,以用于这种替代格式的指令解码。

假定您仍然只有相同数量的寄存器,映射到x86体系结构状态,因此x86 OS可以在上下文切换上保存/恢复它,而无需使用特定于CPU的指令集。但是,如果排除了实际的限制,是的,我们可以有更多的寄存器,因为我们可以使用通常为微码1保留的隐藏临时寄存器。


如果我们只有备用解码器,而对后续的流水线阶段(执行单元)没有任何更改,则此ISA仍然会有很多x86偏心率。 它将不是一个很好的RISC体系结构。没有任何一条指令会非常复杂,但是x86的其他疯狂之处仍然存在。

例如:左/右移位使上溢标志不确定,除非移位计数为1,在这种情况下OF =通常的有符号溢出检测。类似的疯狂旋转。但是,公开的RISC指令可以提供无标志的移位,依此类推(允许仅使用某些复杂的x86指令通常使用的多个微指令中的一两个)。因此,这并不是真正的主要反驳。

如果您打算为RISC ISA制作全新的解码器,则可以让它选择x86指令的一部分作为RISC指令公开。这在某种程度上减轻了内核的x86专业化。


指令编码可能不是固定大小的,因为单个uop可以容纳很多数据。如果所有insn大小都相同,那么数据量就不那么有意义了。一个微融合的uop可以添加一个32位立即数和一个内存操作数,该操作数使用具有2个寄存器和32位位移的寻址模式。(在SnB及更高版本中,只有单寄存器寻址模式才能与ALU ops进行微熔丝连接)。

uops非常大,与固定宽度的ARM指令不太相似。固定宽度的32位指令集一次只能加载16位立即数,因此加载32位地址需要立即加载低半/立即加载高对。x86不必这样做,这仅凭15个GP寄存器限制了在寄存器中保持常数的能力,因此不会很糟糕。(我认为有些模拟发现,15个对7个寄存器有很大帮助,但再加倍至31个对您的帮助就少得多。RSP通常不是通用的,因此更像15个GP寄存器和一个堆栈。)


TL; DR摘要:

无论如何,这个答案归结为“ x86指令集可能是对必须能够快速运行x86指令的CPU进行编程的最佳方法”,但希望可以阐明一些原因。


前端和后端的内部uop格式

另请参阅微融合和寻址模式,以获取前端和后端uop格式在Intel CPU上可以表示的差异的一种情况。

脚注1:有些“隐藏”寄存器被微码用作临时寄存器。就像x86体系结构寄存器一样,这些寄存器也被重命名,因此多uop指令可能会无序执行。

例如,xchg eax, ecx在Intel CPU上,解码为3微码(为什么?),而我们最好的猜测是,它们是类似MOV的微码tmp = eax; ecx=eax ; eax=tmp;。按照这种顺序,因为我测量的是dst-> src方向在〜1个周期内的等待时间,而在2个周期中则是2个。而且,这些动作不像常规mov指令那样。他们似乎不是零延迟运动消除的候选者。

另请参见http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/,其中提到尝试通过实验方式测量PRF大小,并且必须考虑用于保持架构状态的物理寄存器,包括隐藏寄存器。

在解码器之后但在将寄存器重命名到物理寄存器文件的发布/重命名阶段之前的前端中,内部uop格式使用类似于x86 reg编号的寄存器编号,但是有空间来寻址这些隐藏的寄存器。

uop格式在乱序内核(ROB和RS)(也称为后端)(在Issue / rename阶段之后)内有所不同。int / FP物理寄存器文件在Haswell中每个都有168个条目,因此uop中的每个寄存器字段都必须足够宽以解决这么多寄存器。

由于重命名器位于硬件中,因此我们最好使用它,而不是将静态调度的指令直接提供给后端。因此,我们将使用与x86体系结构寄存器+微代码临时性一样大的一组寄存器,而不是更多。

后端旨在与前端重命名器一起使用,以避免WAW / WAR危害,因此即使我们愿意,也不能像有序CPU那样使用它。它没有互锁来检测那些依赖关系。由问题/重命名处理。

如果我们可以将uops送入后端而没有问题/重命名阶段的瓶颈(现代Intel管道中的最窄点,例如Skylake上的4宽vs. 4 ALU + 2负载+ 1的存储端口)后端)。但是,如果您这样做了,我认为您不能静态地调度代码来避免寄存器重用,并且避免由于高速缓存未命中使负载长时间停顿而仍然需要的结果。

因此,我们非常需要将uops输入到issue / rename阶段,可能仅绕过解码,而不是uop缓存或IDQ。然后我们得到了具有健全危害检测功能的普通OoO执行程序。寄存器分配表仅用于将16 +一些整数寄存器重命名为168个条目的整数PRF。我们不能期望硬件将大量的逻辑寄存器重命名为相同数量的物理寄存器。那将需要更大的RAT。


-3

他们为什么不允许我们编译程序,以便他们绕过CISC指令并直接使用RISC内核?

除了先前的答案外,另一个原因是市场细分。某些指令被认为是用微代码而不是硬件来实现的,因此,允许任何人执行任意微操作都可以使用性能更高的“新” CISC指令来破坏新cpus的销售。


1
我认为这没有道理。RISC可以使用微码,特别是如果我们正在谈论仅将RISC解码器添加到x86前端时。
彼得·科德斯

2
那还是错的。AES新指令(以及即将发布的SHA指令)以及PCLMULQDQ等其他东西都具有专用硬件。在Haswell上,AESENC解码为单个uopagner.org/optimize),因此绝对不会对它进行微编码。(解码器只需要激活微码ROM序列器,即可将指令解码到超过4微秒。)
Peter Cordes

1
没错,有些新指令只是以x86指令无法使用的方式使用现有功能。一个很好的例子是BMI2 SHLX,它可以让你变计数的变化,而不把计数CL,并不会产生额外的微指令需要处理蹩脚的x86标志语义(标志是未修改如果移位计数为零,所以SHL r/m32, cl有输入依赖于FLAGS,并在Skylake上解码为3 uop。不过,根据Agner Fog的测试,在Core2 / Nehalem上仅为1 uop。)
Peter Cordes

谢谢您的意见。
KOLANICH '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.