半导体行业观察@这篇说得最详细,关于CPU科普( 二 )


在开始执行刚刚解码的指令之前 , 我们需要暂停片刻以讨论寄存器 。
CPU具有一些很小但非常快的存储器 , 称为寄存器 。 在64位CPU上 , 每个将容纳64位 , 并且内核可能只有几十个 。 这些用于存储当前正在使用的值 , 可以将其视为类似于L0缓存的值 。 在上面的指令示例中 , 值A , B和C都将存储在寄存器中 。
ALU
现在回到执行阶段 。 对于我们上面讨论的3种类型的指令 , 这将有所不同 , 因此我们将分别介绍每一种 。
从算术指令开始 , 因为它们最容易理解 。 这些类型的指令被送入算术日志单元(ALU)进行处理 。 ALU是一种通常具有两个输入和控制信号并输出结果的电路 。
半导体行业观察@这篇说得最详细,关于CPU科普
文章图片
想象一下您在中学时期使用的基本计算器 。 要执行操作 , 请输入两个输入数字以及要执行的操作类型 。 计算器进行计算并输出结果 。 对于我们的CPU的ALU , 操作类型由指令的操作码决定 , 控制单元会将其发送给ALU 。 除了基本的算术运算之外 , ALU还可以执行AND , OR , NOT和XOR之类的bitwise运算 。 ALU还将为控制单元输出一些有关其刚刚完成的计算的状态信息 。 这可能包括诸如结果是肯定的 , 否定的 , 零的还是溢出的事情 。
ALU与算术运算最相关 , 但是它也可以用于存储器或分支指令 。 例如 , CPU可能需要计算作为先前算术运算结果给出的内存地址 。 它还可能需要计算偏移量 , 以添加到分支指令所需的程序计数器中 。 诸如“如果先前的结果是否定的 , 则向前跳20条指令” 。
内存指令和层次结构
对于内存指令 , 我们需要了解一个称为“内存层次结构”的概念 。 这代表了高速缓存 , RAM和主存储之间的关系 。 当CPU接收到一条内存指令 , 该指令针对尚未在其寄存器本地存储的数据时 , 它将沿内存层次结构下降 , 直到找到它为止 。 大多数现代CPU包含三级缓存:L1 , L2和L3 。 CPU首先要检查的地方是L1缓存 。 这是三级缓存中最小和最快的 。 L1高速缓存通常分为用于数据的部分和用于指令的部分 。 请记住 , 指令需要像数据一样从内存中获取 。
典型的L1缓存可能为数百KB 。 如果CPU在L1缓存中找不到所需的内容 , 它将检查L2缓存 。 这可能约为几MB 。 下一步是L3缓存 , 它可能是几十MB 。 如果CPU在三级缓存中找不到所需的数据 , 它将进入RAM , 最后进入主存储器 。 当我们沿着每一步走时 , 可用空间大约增加一个数量级 , 但是等待时间也增加 。
半导体行业观察@这篇说得最详细,关于CPU科普
文章图片
CPU找到数据后 , 它将调出层次结构 , 以便将来如有需要 , CPU可以快速访问它 。 这里有很多步骤 , 但是可以确保CPU快速访问所需的数据 。 例如 , CPU可以在一个或两个周期内读取其内部寄存器 , 在几个周期中读取L1 , 在十个左右周期中读取L2 , 在几十个周期中读取L3 。 如果需要进入内存或主存储 , 则可能要花费数万甚至数百万个周期 。 根据系统的不同 , 每个核心可能会拥有自己的私有L1缓存 , 与另一个核心共享一个L2 , 并在四个或更多核心的组之间共享一个L3 。 我们将在本文后面详细讨论多核CPU 。
分支和跳转指令
三种主要指令类型中的最后一种是分支指令 。 现代程序始终无休止地跳来跳去 , CPU很少执行没有分支的连续指令 。 分支指令来自诸如if语句 , for循环和return语句之类的编程元素 。 这些都用于中断程序执行并切换到代码的不同部分 。 也有跳转指令 , 这些跳转指令是始终采用的分支指令 。
条件分支对于CPU尤其棘手 , 因为它可能一次执行多个指令 , 并且可能直到分支开始执行后续指令后才能确定分支的结果 。
为了完全理解为什么这是一个问题 , 我们需要进行另一种转移 , 并讨论流水线 。 指令周期中的每个步骤可能需要几个周期才能完成 。 这意味着在提取指令时 , ALU否则将处于空闲状态 。 为了最大化CPU的效率 , 我们在称为流水线的过程中划分每个阶段 。