作为程序员,CPU在我们的工作中扮演着核心角色,因此了解处理器的内部工作原理对程序员并非没有好处。 CPU如何工作?一条指令执行需要多长时间?当我们讨论一个新处理器是具有12级流水线还是18级流水线,甚至是更深的31级流水线时,这意味着什么?应用程序通常将CPU视为黑匣子。程序中的指令按顺序进入CPU,然后在执行后按顺序退出CPU。我们通常不知道内部正在发生什么。对于我们的程序员,特别是对于进行程序性能调整的程序员,非常有必要了解CPU的详细信息。否则,如果您不知道CPU的内部结构,那么如何优化CPU的性能?本文重点介绍X86处理器管道的工作原理。您需要掌握的基础知识首先,要阅读本文,您需要了解编程,最好是一点汇编语言。如果您不知道指令指针是什么,那么对您来说这篇文章可能会有些困难。您需要知道什么是寄存器,指令和缓存。如果您不了解它们是什么,则需要尽快查找信息。其次,CPU的工作原理是一个非常大而复杂的话题。本文只是一眼,很难在一篇文章中对其进行详细描述。
如果有任何遗漏,请通过评论告知我。第三,我只关注英特尔处理器及其X86架构。当然,除了X86,还有许多其他体系结构处理器。尽管AMD为X86架构引入了许多新功能,但是X86架构是由Intel发明并创建了X86指令集,其中大多数是由Intel引入的。因此,为了使描述简单和一致,我仅关注英特尔处理器。最后,当您阅读本文时,它已经“过时”了。已经设计出了更新的处理器,其中一些将在未来几个月内发布。我很高兴技术可以如此迅速地发展,我希望有一天所有这些技术都将过时,并创建具有更强大计算能力的CPU。处理器管道的基础知识从非常广泛的角度来看,X86处理器体系结构在过去35年中没有太大变化。尽管X86体系结构已添加了许多新功能,但是即使最新的处理器仍支持原始设计(包括几乎所有原始指令集),该设计仍基本完好。原始的8086处理器支持14个寄存器,而今天的最新处理器中仍然存在这些寄存器。在这14个寄存器中,有4个是通用寄存器:AX,BX,CX和DX; 4是段寄存器,用于辅助指针的实现:代码段(CS),数据段(DS),扩展段(ES)和堆栈段(SS);有4个用于指向存储器地址的索引寄存器:源引用(SI),目标引用(DI),基本指针(BP),堆栈指针(SP);每个寄存器包含1个状态位;最后一个是最重要的寄存器:指令指针(IP)。
指令指针寄存器是具有特殊功能的指针。指令指针的功能是指向要执行的下一条指令。所有X86处理器均以相同的模式运行。首先,根据指令指针指向的地址获取要执行的下一条指令,并解析该指令(解码)。解码完成后,将有一个指令执行阶段。一些指令用于从存储器读取数据或将数据写入存储器,而某些指令用于执行计算或比较。执行该指令时,该指令将通过退出阶段,并将指令指针修改为下一条指令。解码,执行和退出的三级流水线构成了X86处理器指令执行的基本模式。从原始的8086处理器到最新的Core i7处理器,基本上都遵循此过程。尽管更新的处理器增加了更多的流水线级,但是基本模型没有改变。 35年中发生的变化与当今的标准相比,原始处理器设计似乎过于简单。原始8086处理器的执行过程可以简要描述为从当前指令指针获取指令,对其进行解码,执行并最终退出,然后继续从指令指针指向的下一条指令获取指令。新的处理器增加了新的功能,有些增加了新的指令,有些增加了新的寄存器。我将主要关注与本文主题相关的更改,这些更改会影响CPU指令执行的流程。其他更改(例如虚拟内存或并行处理)是有意义且有趣的,但它们不在本文主题范围之内。

指令高速缓存是在1982年添加到处理器中的。通过指令高速缓存,处理器可以一次从内存中读取更多指令并将其放入指令高速缓存中,而不是从内存中提取每条指令。指令高速缓存的大小只有几个字节,并且只能容纳几个指令,但是由于它消除了随后每次从存储器和处理器中提取数据的时间,因此效率得到了极大的提高。 1985年,386处理器引入了数据缓存。 ,并扩展了指令缓存的设计。数据读取请求通过一次读取更多数据并将其放置在数据缓存中来提高性能。而且,数据高速缓存和指令高速缓存都从几个字节扩展到了几千字节。 1989年推出的i486处理器引入了五级流水线。此时,CPU中不再只有一条指令在运行,并且流水线的每一级都在同时运行另一条指令。这种设计使i486的性能达到了相同频率386个处理器的两倍。五级流水线中的指令获取阶段从指令高速缓存中获取指令(i486中的指令高速缓存为8KB)。第二阶段是解码阶段,将提取的指令转换为特定的功能操作。第三阶段是转发阶段,用于转换内存地址和偏移量;第四阶段是执行阶段,在该阶段实际执行指令。第五阶段是退出阶段,将运算结果写回到寄存器或存储器。因为处理器同时运行多个指令,所以程序的性能大大提高了。 1993年,英特尔推出了奔腾处理器。
由于诉讼问题,英特尔无法继续使用原始编号。因此,奔腾将586替换为新处理器的代号。与i486处理器相比,奔腾处理器对管线进行了更多更改。奔腾处理器架构增加了第二条独立的超标量流水线。主流水线的工作方式类似于i486,第二条流水线并行运行一些更简单的指令(例如定点算术),并且流水线可以更快地执行操作。 1995年,英特尔推出了奔腾Pro处理器。与以前的处理器相比,奔腾Pro采用了完全不同的设计。该处理器使用许多新功能来提高性能,包括乱序(Out-of-order,OOO)执行组件和推测性执行。流水线已扩展到12个阶段,并且引入了“超标量流水线”的概念,因此可以同时处理许多指令。稍后,我们将详细介绍乱序执行组件。在1995年至2002年之间,乱序执行组件进行了几项重大改进。更多寄存器已添加到处理器;单指令多数据(或SIMD)的引入允许一条指令执行多个数据操作;现有的缓存已经变大,并且引入了新的缓存;一些管道阶段被分成更多的管道阶段,并且某些管道阶段被合并,使其更适合于实际应用。
这些更改对整体性能的提高有重要影响,但它们并没有从根本上影响处理器中数据流的方式。 2002年发布的Pentium 4处理器引入了超线程技术。乱序执行组件的设计使指令的执行速度比处理器提供的指令要快。因此,对于大多数应用程序而言,CPU的乱序执行组件大部分时间都是空闲的,即使在高负载条件下也无法充分利用。为了使指令流完全流入乱序执行组件,英特尔添加了第二套前端组件(注释:在处理器结构中,前端指的是诸如获取,解码,寄存器重命名等,由前端组件处理,然后,该指令等待启动进入乱序执行单元。尽管实际上只有一个乱序执行组件,但是对于操作系统,它可以看到两个处理器。前端组件包含两组具有相同功能的X86寄存器。两个指令根据两个指令指针所指向的地址分别进行处理。所有指令均由共享的无序执行组件执行,但应用程序不知道。当按顺序执行无序执行组件并退出流水线时,最终结果将返回到两个虚拟处理器。 2006年,英特尔发布了Core微体系结构。出于品牌效应,它称为Core 2(两个胜于一个)。出人意料的是,处理器频率没有上升而是下降了,超线程被删除了。通过降低时钟频率,流水线的每个阶段都可以做更多的工作。
乱序执行组件也得到了扩展。相应地使各种缓冲区和队列变大。并且处理器已经过重新设计,以适应双核和四核共享缓存结构。 2008年,英特尔开始使用Core i3,i5和i7命名新处理器。新处理器重新引入了超线程。这三个系列处理器之间的主要区别是内部缓存的大小。未来的处理器:英特尔的下一代微结构称为Haswell。据说Haswell将于2013年发布。目前已知的文件表明,它将有14个流水线级的无序执行组件,因此它仍然遵循自Pentium Pro以来的基本设计思想。那么,组装线到底是什么?什么是乱序执行组件?他们如何提高处理器的性能? CPU指令流水线基于前面所述的基础。指令进入管道,通过管道进行处理以及退出管道的过程对我们的程序员而言相对直观。 I486具有五级流水线。它们是:获取(Fetch),解码(D1,主解码),正向(D2,转换),执行(EX,执行),回写(WB)。一条指令可以在管道的任何阶段。但是,这样的管道具有明显的缺陷。对于以下指令代码,它们的功能是交换两个变量的内容。
1 XOR a,b 2 XOR b,a 3 XOR a,b没有从8086到386处理器的流水线。处理器一次只能执行一条指令。在这样的架构下,上面的代码执行将不会成为问题。但是i486处理器是第一个具有管道的x86处理器,当它执行上述代码时会发生什么?当您查看流水线中运行的许多指令时,您会感到困惑,因此您需要参考上图。第一步是第一条指令进入指令提取阶段。然后在第二步骤中,第一条指令进入解码阶段,而第二条指令进入指令提取阶段。第三条指令进入索引阶段,第一条指令进入解码阶段,第三条指令进入指令提取阶段。但是第四步会出现问题,第一条指令将进入执行阶段,而其他指令无法继续前进。第二个xor指令需要由第一个xor指令计算出的结果a,但是直到执行第一个指令后才将其写回。因此,流水线中的其他指令将在当前流水线阶段等待,直到第一条指令的执行和写回阶段完成。第二条指令将在进入管线的下一级之前等待第一条指令的完成,而第三条指令还将等待第二条指令的完成。这种现象称为管道阻塞或管道气泡。流水线的另一个问题是某些指令速度很快,而某些指令速度很慢。在奔腾处理器的双流水线架构下,这个问题更加明显。
奔腾Pro具有12级流水线。首次公布此数字时,所有程序员都松了一口气,因为他们知道超标量管道的工作方式。如果英特尔仍然根据先前的想法设计超标量管线,则管线的阻塞和指令的缓慢执行将严重影响执行速度。但与此同时,英特尔宣布了一种完全不同的流水线设计,称为无序内核。仅凭叙述很难理解这些变化的好处,但英特尔深信这些改进令人振奋。让我们仔细看看这个乱序的执行组件!乱序执行流水线当描述乱序执行流水线时,一张图片通常值一千个字。所以我们主要介绍传说。 CPU流水线图例I486处理器具有5级流水线。这种设计在现实世界中的其他处理器中很常见,并且非常有效。奔腾处理器的管线优于i486。两个管道可以并行运行,并且每个管道可以同时在不同的管道阶段执行多个指令。它可以同时执行几乎是i486两倍的指令。可以快速完成的指令即使在并行管道中也需要等待执行缓慢的先前指令,这仍然是一个问题。流水线仍然是线性的,导致处理器面临无法克服的性能瓶颈。乱序执行组件与先前处理器设计中的线性路径有很大不同。它增加了一些复杂性,并引入了非线性路径。
第一个更改是从内存中获取指令到处理器指令高速缓存的过程。现代处理器可以检测到何时会发生大的分支跳转(例如函数调用),然后将跳转目标指令预先加载到指令缓存中。解码阶段稍作修改。与以前的处理器仅解码指令指针指向的指令不同,奔腾Pro处理器每个周期最多可以解码3条指令。当今的处理器(2008-2013)每个时钟周期最多可以解码4条指令。解码过程会产生许多小的操作,称为微操作(?-ops)。下一级别(或几个级别)称为微指令转换,然后是寄存器别名。许多操作是同时执行的,并且执行的顺序是乱序的,因此有可能在一条指令读取一个寄存器的同时,另一条指令正在写入该寄存器。在处理器内部,这些原始寄存器(例如AX,BX,CX,DX等)被转换(或重命名)为内部寄存器,并且程序员看不到这些寄存器。寄存器和存储器地址需要映射到一个临时位置以执行指令。目前,每个周期可以翻译4条微指令。翻译微指令时,它们将输入重新排序缓冲区(ROB)。 ROB最多可以存储128条微指令。
在支持超线程的处理器上,ROB还可以重新排列来自两个虚拟处理器的指令。这两个虚拟处理器将微指令组合到ROB中共享的乱序执行单元中。这些微指令准备执行。它们被放置在预订站(Reservation Station,RS)中。 RS可以同时存储多达36条微指令。直到现在,小部件的魔术部分才按顺序执行。在不同的执行单元中同时执行不同的微指令,并且每个执行单元均以全速运行。只要当前微指令所需的数据准备就绪,并且有一个空闲的执行单元,微指令就可以立即执行,有时甚至可以跳过之前尚未准备就绪的微指令。这样一来,需要长时间运行的操作就不会阻塞后续的操作,大大减少了管线阻塞造成的损失。 Pentium Pro的乱序执行单元有6个执行单元:两个定点处理单元,一个浮点处理单元,一个获取单元,一个地址存储单元和一个存储单元。这两个定点处理单元不同,一个可以处理复杂的定点运算,另一个可以同时处理两个简单的运算。在理想条件下,Pentium Pro的乱序执行单元可以在一个时钟周期内执行7条微指令。如今,乱序执行组件仍具有6个执行单元。其中,获取单元,地址单元和数字存储单元未更改,而其他三个则有所更改。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-345153-1.html
美国不敢打
祖宗留给我们的江海疆土绝不容侵犯