- wpwipi
-
CPU通常被称为计算机的大脑,就像人脑一样。它由几个部分组成,包括接收信息的部分、存储信息的部分、处理信息的部分、帮助输出信息的部分等等。这些部分一起工作来处理信息。
在今天 的文章中,我们将介绍构成CPU的关键元素,以及它们如何一起为计算机提供动能。
CPU蓝图:ISA
在分析任何一个CPU的时候,首先遇到的就是指令集架构。这是一个关于CPU如何运行以及所有内部系统如何交互的图形蓝图。就像同一物种有很多品种的狗一样,在CPU上可以构建很多不同类型的isa。两种最常见的类型是x86和ARM。
还有其他利基应用程序,如MIPS、RISC-V和PowerPC。ISA将指定CPU可以处理哪些指令,如何与内存和缓存交互,如何在多个处理阶段中划分工作,等等。
为了涵盖CPU的主要部分,我们将遵循一条指令执行时所采取的路径。不同类型的指令可能遵循不同的路径,并使用CPU的不同部分,但这里我们将概括涵盖最大的部分。我们将从单核处理器的最基本设计开始,随着我们向更现代的设计发展,逐渐增加复杂性。
控制单元和数据路径
CPU可分为控制单元和数据通路两部分。想象一列火车。发动机是火车的动力源,但车长在幕后拉动操纵杆,控制着发动机的方方面面。CPU也是这样。
数据就像一个引擎。顾名思义,它是数据在处理过程中流动的路径。数据路径接收输入,处理它们,并在完成时将它们发送到正确的位置。控制单元告诉数据路径如何工作。根据指令,数据路径将信号路由到不同的组件,打开和关闭数据路径的不同部分,并监控CPU的状态。
指令周期-获取
我们的CPU要做的第一件事就是搞清楚接下来要执行什么指令,然后把指令从内存转移到CPU。指令由编译器生成,并且特定于CPU的ISA。ISAs将共享最常见的指令类型,如加载、存储、加、减等。但每个特定的ISA都有许多其他特殊类型的指令。对于每种类型的指令,控制单元将知道哪些信号需要路由到哪里。
比如跑步的时候。exe在Windows上,程序的代码会移入内存,并告诉CPU第一条指令的起始地址。CPU总是维护一个内部寄存器,用于保存下一条要执行的指令的存储位置。这被称为程序计数器。
一旦你知道从哪里开始,指令周期的第一步就是获取指令。这将把指令从内存移动到CPU的指令寄存器,称为取指令阶段。实际上,该指令可能已经在CPU的缓存中,这一点我们将在后面介绍。
指令周期-解码
当CPU有一条指令的时候,需要具体弄清楚是什么类型的指令。这被称为解码阶段。每条指令都有一组称为操作码的特定位,告诉CPU如何解释它。这类似于如何使用不同的文件扩展名来告诉计算机如何解释文件。例如,jpg和。png都是图像文件,但它们以不同的方式组织数据,因此计算机需要知道它们的类型才能正确地解释它们。
根据ISA的复杂程度,CPU的指令解码部分可能会变得复杂。像RISC-V这样的ISA可能只有几十条指令,而x86有上千条指令。在典型的英特尔x86 CPU上,解码过程是最具挑战性的过程之一,并且占用大量空间。由CPU解码的最常见的指令类型是内存、算术或分支指令。
3种主要指令类型
存储指令可能类似于 quot从内存地址1234读入值A quot或者 quot将值B写入内存地址5678 quot。算术指令可以类似于 quot将值A加到值B,并将结果存储到值C quot。分支指令可能类似于 quot如果C的值为正,则执行这段代码;如果c的值为负,则执行该代码 quot。一个典型的程序可能会将它们链接在一起,产生类似于 quot将结果为正的内存地址1234的值与内存地址5678的值相加,并将其存储在内存地址4321中,如果结果为负,则将其存储在地址8765中。
在开始执行刚刚解码的指令之前,我们需要暂停一会儿来讨论寄存器。
CPU有一些很小但速度很快的内存,叫做寄存器。在一个64位的CPU上,每个将容纳64位,并且可能只有几十个核心。这些用来存储当前使用的值,可以认为是类似于L0缓存的值。在上面的指令示例中,值A、B和C都将存储在寄存器中。
ALU
现在返回执行阶段。对于我们上面讨论的3种类型的指令,这将是不同的,所以我们将分别介绍每一种。
从算术指令开始,因为它们最容易理解。这些类型的指令被发送到算术对数单元进行处理。ALU是一种通常有两个输入和控制信号并输出结果的电路。
想象一下你在中学使用的基本计算器。要执行操作,请输入两个输入数字和要执行的操作类型。计算器计算并输出结果。对于我们的CPU ALU,操作类型由指令的操作码决定,控制单元会发送给ALU。除了基本的算术运算之外,ALU还可以执行按位运算,例如AND、OR、NOT和XOR。ALU还将向控制单元输出一些关于其刚刚完成的计算的状态信息。这可能包括诸如结果是正、负、零还是溢出之类的事情。
ALU与算术运算最相关,但它也可用于内存或分支指令。例如,CPU可能需要计算作为前面算术运算结果的内存地址。它可能还需要计算偏移量,以添加到分支指令所需的程序计数器中。比如 quot如果前面的结果是否定的,向前跳20个指令 quot。
内存指令和层次结构
对于内存指令,我们需要知道一个叫做 quot内存层次 quot。这代表了高速缓存、RAM和主存储器之间的关系。当CPU接收到一个针对没有本地存储在其寄存器中的数据的内存指令时,它将沿着内存层次结构向下移动,直到找到它。大多数现代CPU包含三级高速缓存:L1、L2和L3。CPU检查的第一个地方是L1缓存。这是最小和最快的三级缓存。L1缓存通常分为数据部分和指令部分。记住,指令需要像数据一样从内存中检索。
典型的L1缓存可能有数百KB。如果CPU能 如果在L1缓存中找不到它需要的内容,它将检查L2缓存。这可能是几个兆字节。下一步是L3缓存,可能是几十MB。如果CPU能 如果在三级高速缓存中找不到所需的数据,这些数据将进入RAM并最终进入主存。我们每走一步,可用空间就增加一个数量级,但等待时间也会增加。
在CPU找到数据后,它将调用层次结构,以便CPU在将来需要时可以快速访问它。这里的步骤很多,但能保证CPU快速访问所需数据。例如,CPU可以在一两个周期内读取其内部寄存器,L1需要几个周期,L2大约需要十个周期,L3需要几十个周期。如果需要访问内存或主存,可能需要几万甚至几百万个周期。根据系统的不同,每个内核可能有自己的专用L1缓存,与另一个内核共享一个L2,并在四个或更多内核的组之间共享一个L3。我们将在本文后面详细讨论多核CPU。
分支和跳转指令
三种主要指令类型中的最后一种是分支指令。现代的程序总是无休止地跳来跳去,CPU很少执行没有分支的连续指令。分支指令来自if语句、for循环和return语句等编程元素。这些用于中断程序执行和切换到代码的不同部分。还有跳转指令,总是分支指令。
对于CPU来说,条件分支尤其棘手,因为它可能一次执行多条指令,并且在分支开始执行后续指令之前,分支的结果可能无法确定。
为了充分理解为什么这是一个问题,我们需要进行另一次传输并讨论管道。指令周期中的每个步骤可能需要几个周期才能完成。这意味着当获取指令时,ALU将空闲。为了最大限度地提高CPU的效率,我们将每个阶段划分为一个称为流水线的过程。
理解这一点的经典方法是比较洗衣服。你有两件东西要洗。洗一个晾一个要一个小时。可以将第一件物品放入洗衣机,然后放入烘干机,烘干后再开始洗第二件物品。需要四个小时。但如果分工,在第一件产品干的同时开始第二次洗涤,三个小时就可以完成两次洗涤。一小时的减少量取决于你要洗的衣服数量以及洗衣机和烘干机的数量。仍然需要两个小时来干燥所有东西,但是如果计算重叠,总吞吐量将从0.5个产品/小时增加到0.75个产品/小时。
CPU使用相同的方法来提高指令吞吐量。现代ARM或x86 CPU可能有20多个流水线阶段,这意味着在任何给定的时间点,内核都可以同时处理20多条不同的指令。每种设计都是独特的,但是样本分区可以是4个周期用于读取,6个周期用于解码,3个周期用于执行,7个周期用于将结果更新回存储器。
回到分公司,希望你能开始看到这个问题。如果我们不 直到第10个周期,我们才知道一条指令是分支,那么我们将已经开始执行9条新指令,如果采用这个分支,这些指令可能是无效的。为了解决这个问题,CPU有一个非常复杂的结构,叫做分支预测器。他们使用机器学习中类似的概念,试图猜测分支是否会被采用。分支预测变量的复杂性远远超出了本文的范围,但是在基本层面上,它们跟踪以前分支的状态,以查看是否有可能采用即将到来的分支。现代分支预测器可以具有95%或更高的准确度。
一旦分支的结果被确定,程序计数器将被更新,CPU将继续执行下一条指令。如果分支的预测是错误的,CPU会在分支开始错误执行后抛出所有指令,然后从正确的位置重新开始。
当前位置现在,我们知道了如何执行三种最常见的指令。让 让我们看看CPU的一些更高级的功能。实际上,所有现代处理器都不 实际上并不按照接收的顺序执行指令。在等待其他指令时,您可以使用一个名为无序执行的示例来最小化停机时间。
如果CPU知道即将到来的指令,但所需的数据可以 如果没有及时准备好,那么它可以在等待时切换指令序列,并从程序后面引入一条独立的指令。这种指令重排序是一种非常强大的工具,但它远不是CPU使用的唯一技能。
另一个提高性能的特性叫做预取。如果你从头到尾完成一条随机指令都要花时间,你会发现大部分时间内存访问都用光了。预取器是CPU中的一个单元,它试图预测未来的指令以及它们将需要什么数据。如果您发现需要由CPU缓存的数据,它将到达RAM并将数据提取到缓存中。所以它的名字叫预取。
乱序执行
在CPU中,正在添加的另一个主要功能是特定任务的加速。这些电路的全部工作就是尽可能快地完成一个小任务。这可能包括加密、媒体编码或机器学习。
CPU可以自己做这些事情,但是有一个专用于它们的单元会大大提高效率。专用GPU就是一个很好的例子。当然,CPU可以执行图形处理所需的计算,但为其配备专用单元可以提供更好的性能数量级。随着加速器的兴起,CPU的实际核心可能只占芯片的一小部分。
下图是几年前的英特尔CPU。内核和缓存占据了大部分空间。下面第二张图是新的AMD芯片。那里的大部分空间被核心之外的组件占据。
加速器与未来
最后要介绍的主要功能是如何将一堆单独的CPU连接在一起,形成一个多核CPU。它 这并不像我们之前讨论的简单地将单核设计放入多个副本中那么简单。正如没有简单的方法可以将单线程程序转换成多线程程序一样,同样的概念也适用于硬件。从问题的核心之间的依赖。
例如,对于4核设计,CPU发出指令的速度需要提高4倍。它还需要四个独立的存储器接口。由于多个实体可能处理相同的数据,因此必须解决一致性和不一致性等问题。如果两个内核使用相同的数据来处理指令,那么它们如何知道谁拥有正确的值呢?如果一个内核修改了数据,但是没有 不能及时到达另一个内核执行?因为它们有单独的缓存可以存储重叠的数据,所以必须使用复杂的算法和控制器来消除这些冲突。
随着CPU内核数量的增加,正确的分支预测也非常重要。内核一次执行的指令越多,其中一个处理分支指令的可能性就越大。这意味着指令流可能随时改变。
通常,一个独立的内核将处理来自不同线程的指令流。这有助于减少内核之间的依赖性。那 这就是为什么如果您查看任务管理器,您会经常看到一个内核正在努力工作,而其他内核正在工作。许多程序不是为多线程设计的。在某些情况下,让一个内核完成工作要比试图划分工作所付出的代价高得多。
走向多核
本文的大部分内容都集中在CPU的架构设计上,因为这是大部分复杂性所在。然而,所有这些都需要在现实世界中创建,这增加了另一个层次的复杂性。
为了同步整个处理器中的所有组件,使用了时钟信号。现代处理器通常运行在3.0GHz到5.0GHz之间,它们不会 在过去的十年里,似乎没有什么变化。在每个周期中,芯片内部数十亿个晶体管被开启和关闭。
时钟是必不可少的,以确保所有的值显示在正确的时间,因为每个阶段的管道进展。时钟决定了CPU每秒可以处理多少条指令。通过超频提高它的频率会让芯片更快,但也会增加功耗和热量输出。
热量是CPU最大的敌人。随着数字电子设备温度的升高,微晶体管可能会开始退化。如果不散热,芯片可能会损坏。那 这就是为什么所有的CPU都有散热器。CPU的实际硅片可能只占物理设备表面积的20%。占据空间的增加使得热量更均匀地分布到散热器上。它还允许使用更多引脚与外部元件接口。
现代CPU的背面可以有成千上万或更多的输入和输出引脚。由于大多数计算组件都在芯片中,移动芯片可能只有几百个引脚。无论采用哪种设计,都有一半左右专用于供电,其余用于数据通信。这包括与内存、芯片组、存储、PCIe设备等的通信。
由于高性能CPU在满载时消耗100安培或更多,它们需要数百个引脚来均匀分布电流消耗。插脚通常镀金以提高导电性。不同的制造商在他们的许多产品线中使用不同的引脚排列。
物理设计
总结一下,我们就快速介绍一下英特尔酷睿2 CPU的设计。这开始于2006年,所以有些部分可能已经过时了,但没有关于更新设计的详细信息。
从顶部开始,我们有指令缓存和ITLB。翻译后备缓冲器用于帮助CPU知道所需指令在内存中的位置。这些指令存储在L1指令缓存中,然后发送到预解码器。x86架构极其复杂密集,解码步骤非常多。与此同时,分支预测器和预取器都在预期由到来的指令引起的任何潜在问题。
从那里,指令被发送到指令队列。复习无序设计如何让CPU执行指令,选择最及时的指令执行。该队列保存CPU正在考虑的当前指令。一旦CPU知道哪条指令将是最好的执行方式,它将被进一步解码成微操作。虽然一条指令可能包含CPU的复杂任务,但微操作是一项微妙的任务,可以更容易地由CPU来解释。
然后,这些指令输入 quot注册表 quot, quot罗布 quot和 quot预订站 quot。这三个组件的确切功能有些复杂,但它们用于帮助管理无序过程中指令之间的依赖关系。
A quot核心 quot实际上会有许多alu和内存端口。将输入操作放入保留站,直到ALU或内存端口可以使用。一旦所需组件可用,该指令将在L1数据缓存的帮助下进行处理。输出将被存储,CPU现在准备好从下一条指令开始。那 就是它!
虽然本文并不打算准确地指导每个CPU如何工作,但是它应该让您很好地理解它们的内部工作原理和复杂性。坦白说,AMD和英特尔以外的人其实不 我不知道他们的中央处理器是如何工作的。本文的每一部分都代表了整个研发领域,因此这里提供的信息只是一个开始。
来源:内容由icbank整理自techspot。谢谢你。
王者之心2点击试玩