【计算机体系结构-04】流水线:基础与中级概念 (Pipelinling: Basic and Intermediate Concepts)

news2025/1/11 17:52:07

1. 借题引入

在亚当·斯密所著的《国富论》一书中有描述过这样的场景,扣针制造业中制造一个扣针需要先后完成抽铁丝、拉直、切截、削尖铁丝的一端、打磨铁丝的另一端(以便安装圆头),制作圆头也需要二三种不同的操作,包括装圆头、涂白、包装这些工序。这样详细的划分后,制作一个扣针的步骤被分为 18 道工序。有一个小的工厂中为制作扣针雇佣了十个工人,其中有几个工人需要兼顾完成两三道工序,在这样小工厂中虽然资源匮乏的就连必要的机械设备也很简陋,但只要每个工人都勤勉地工作,一天也能生产出 12 磅扣针,每磅扣针约有 4000 枚,这样这个工厂每天可以生产出 48000 枚扣针,即每人每天可以制造出 4800 枚。如果这些工人没有分工合作而是各自独立完成扣针制作,恐怕没有任何一个人可以完成一天 4800 枚的目标。

2. 流水线

实际上上面的例子已经是一个流水线业务了,一条生产线由 10 个工人来承担,那么我们称这样的生产线为 10 级流水线([注]:超过 5 级流水线也被称为超流水线。

在计算机中,流水线是一种将多条指令重叠执行的实现技术。我们知道一条指令的执行需要多个操作,而流水线技术就是充分利用了这些操作之间的并行性。如今流水线是用于加快 CPU 速度的关键实现技术。

就像上面的扣针生产线,在一条生产线上由多个工人分别负责不同的任务共同协作完成一个扣针的制作,并且工人之间的执行的动作步骤都是并行的。计算机中的流水线也一样,流水线中的每个步骤完成指令的一部分,不同步骤并行完成指令中的不同部分。而这些步骤中的每一步被称为流水级 (pipe stage) 或流水段 (pipe segment)。流水级前后连接形成流水线,指令将从流水线的一端进入,通过这些流水级从另一端退出。

在扣针生产线中,吞吐量 (throughput) 定义为每小时生产的扣针数量,由完整的扣针退出生产线的频率决定。类似的,指令流水线的吞吐量由指令退出流水线的频率决定。所有流水级是连在一起的,所以每个流水级都必须做好同时工作的准备(并行工作)。

将一条指令在流水线中下移一步所需要的时间为处理器周期 (processor cycle)。因为是所有流水级同时进行,那么处理器周期的长度则由最慢的流水级所需要的时间决定。在计算机中,这一处理器周期通常为 1 个时钟周期(有时也会是 2 个,但非常少见)。

流水线设计者的目标是平衡每条流水线的长度,就像扣针生产线的设计者尝试拆分制作步骤并平衡每个步骤的时间一样。如果各流水级达到完美平衡,那么每条指令在流水线处理器 (pipelined processor) 上的时间(假定为理想条件)就等于:

在这里插入图片描述

在这样的条件下,因为实现了流水线,从而得到的加速比等于流水级的数目,就像一个 n 级生产线在理想情况下可以将扣针生产速度提高至 n 倍一样。但一般情况,这些流水线之间不会达到完美平衡,此外,流水线本身还会产生开销。因此,在流水线处理器上,处理每条指令的时间不会等于其最低可能指,但可以非常接近。

流水线可以缩短每条指令的平均执行时间。 这一缩短量可记作每条指令时钟周期数 (CPI-Clock Cycle Per Instruction) 的下降、时钟周期时间的缩短,或者这两者的组合。如果在开始时,处理器需要多个时钟周期来处理一条指令,那么将认为流水线的作用时降低了 CPI;而如果在开始时,处理器需要一个较长的时钟周期来处理一条指令,那么就认为流水线是缩短了时钟周期的时间。

3. RISC 指令集基础知识

精简指令集 RISC 是一种载入——存储体系结构 (Load-Store Architecture)。所有的 RISC 架构都有以下几个关键属性。

  • 所有数据操作都是对寄存器中的操作,通常会改变整个寄存器(每个寄存器为 32 位或 64 位);
  • 仅有 LoadStore 操作会影响存储器,他们分别将数据从存储器移到寄存器或从寄存器移到存储器。
  • 指令格式相对固定,所有指令位宽通常相同。在 RISC-V 中,寄存器说明符 rs1rs2rd 总是固定在同一个位置编码从而简化了控制。

这些简单属性极大的简化了流水线的实现,这也是这样设计这些指令集的原因。这里假定各位读者已经了解了 RISC-V ISA。若没有,则可以通过笔者的这篇博客快速了解《RISC-V ISA》文章待编写,链接待添加。

4. RISC 指令集的简单实现

先来看不采用流水线是如何实现 RISC 指令集,此处用一种简单的实现来描述,在 RISC 子集中的每条指令最多需要 5 个时钟周期完成。这 5 个时钟周期如下所述:

  • (1) 指令提取周期 (IF-Instruction Fetch)
      将程序计数器 (PC-Program Counter) 发送到存储器,从存储器提取当前指令。向程序计数器加 4MIPS 每条指令的长度位 4 个字节),将程序计数器更新到下一个连续程序计数器;
  • (2) 指令译码/寄存器提取周期 (ID-Instruction Decode)
      对提取到的指令译码,并从寄存器堆中读取与寄存器源说明符相对应的寄存器。在读取寄存器时对其进行相等测试,以确定是否为分支。
      指令译码与寄存器的读取时并行执行的,这可能是因为在 RISC 体系结构中,寄存器描述符位于固定位置。这一技术称为固定字段译码 (Fixed-Field Decoding)。需要注意的是,这里也许会读取一个寄存器但并不会使用,虽然这么做没有什么好处,但也不会影响到性能。(由于读取寄存器与译码在同一个周期完成,读取一个不会用到的寄存器,从时间上来讲并没有增加。不过这样的读取无需寄存器的确会增加功耗,特定场景下的设计可以避免这个问题。)由于一个指令的立即数部分也位于同一位置,所以在需要符号扩展立即数时,也是在这一周期计算。
  • (3) 执行/有效地址周期 (EX-Execution)
    ALU 对上一周期中准备的操作数进行操作,根据指令类型执行四种操作之一。
    <1> 存储器访问——ALU 将基址寄存器和偏移量加到一起,形成有效地址;
    <2> 寄存器-寄存器 ALU 指令——ALU 用读取到的寄存器堆值,根据 ALU 操作码执行指定操作;
    <3> 寄存器-立即数 ALU 指令——ALU 用读取到的寄存器堆的第一个值和符号扩展立即数执行 ALU 操作码指定的操作;
    <4> 条件分支——判断条件是否为真。
      在 Load-Store 体系结构中,有效地址与执行周期何以合并到一个时钟周期中,这是因为没有指令需要同时计算数据地址并对数据执行操作。
  • (4) 存储器访问 (MEM-Memory)
      如果该指令是一条 load 指令,则使用上一周期计算的有效地址从存储器中读取数据。如果是一条 store 指令,则使用有效地址将从寄存器堆的第二个寄存器读取的数据写入存储器。
  • (5) 写回周期 (WB-Write Back)
    <1> 寄存器-寄存器 ALU 指令或 load 指令。
      将结果写入寄存器堆,无论是来自寄存器系统(load 指令),还是来自 ALUALU 指令)。

在这样的设计中,分支指令需要 3 个时钟周期(IF、ID、EX),存储指令需要 4 个周期(IF、ID、EX、MEM),其它所有指令需要 5 个周期。假设分支频率为 12%,存储频率为 10%,对于这样的典型指令分布,总的 CPI4.66。(12% × 3 + 10% × 4 + 78% × 5 = 4.66

5. RISC 处理器的经典五级流水线

对于上面的无流水线指令集的实现,几乎不用进行什么改造就可以实现流水化,只需要在每个时钟周期开始一条新的指令就行,即将上面的每个时钟周期变成一个流水级完成了流水化。这样的实现的流水线就会像下面这样。
在这里插入图片描述
在每个时钟周期,提取另一条指令,并开始它的五个周期的执行过程。如果在每个时钟周期都启动一条指令,其性能最多可达非流水化处理器的 5 倍。流水线中各个阶段的名称与非流水线实现方式中每个周期的名称相同。

上面的流水化是一种理想情况的设计。首先要确定的是流水线处理器的每个时钟周期都会发生什么,确保不会在同一时钟周期内对相同数据路径源执行两个不同操作。

在这里插入图片描述
[注]:该图描述的是各流水级之间的数据路径。
CC (Clock Cycle): 时钟周期;
IM (Instruction Memory): 指令存储器;
Reg (Register): 寄存器;
ALU (Arithmetic Logic Unit): 算术逻辑单元;
DM (Data Memory): 数据存储器;
上图绘制了一个 RISC 数据路径的简化版。IF 周期从 IM 中提取指令,ID 周期读寄存器并译码指令,EX 周期使用 ALU 计算有效地址,MEM 周期一周期计算的有效地址从存储器中读取数据(Load 指令),或直接使用有效地址将从寄存器堆的第二个寄存器读取的数据写入存储器(ALU 指令),WB 周期将结果写入寄存器。

从以下三点可以看出,主要功能单元是在不同周期使用的,因此多条指令的执行重叠不会引入多少冲突。

第一,这里使用分离的指令存储器 IM 和数据存储器 DM 从而避免了指令提取和数据存储器访问之间可能会发生的冲突。
[注]:若流水线处理器的时钟周期等于非流水线版本的时钟周期,则存储器系统必须提供 5 倍的带宽。

第二,在该过程中的两个阶段都使用了寄存器堆,一个是在 ID 中读取,一个是在 WB 中写入。 图中为了描述寄存器的一部分在该流水级进行读取,另一部分进行写入,分别用左右两侧的实线或虚线来表示。因此可以看到每个时钟周期需要执行两次读取和一次写入,为了处理对相同寄存器的多次读取和一次写入,将这样设计,在时钟周期的前半部分写寄存器,在后半部分读寄存器。

第三,上图并没有给出程序计数器 PC,为了在每个时钟周期都启动一条新的指令,我们必须在每个时钟周期使程序计数器递增并存储它,这必须在 IF 阶段完成,以便为下一条指令做好准备。另外还需要一个加法器,在 ID 期间计算潜在的分支目标。

尽管确保了流水线中的指令不会因为试图在同一个时钟周期使用同一个硬件资源导致的冲突。现在还必须要确保不同流水级之间的指令不会相互干扰。可以通过在连续流水级之间引入流水线寄存器来完成,即在时钟周期的末尾将流水级得出的所有结果都保存到寄存器中,在下一个时钟周期作为下一级的输入。

在这里插入图片描述

为了防止流水级相邻级中两条不同指令之间的干扰而引入流水线寄存器,由于寄存器具有边沿触发特性,即取值在时钟沿即使改变。在流水化处理器中,如果要将中间结果从一级传送到另一级,而原位置与目标位置可能并非直接相邻此时流水线寄存器则发挥着关键作用(因为只有寄存器中的值在跨越时钟边界后任得以保存)。例如,load 指令中存储的寄存器值是在 ID 期间读取的,但要等到 MEM 才会真正用到,它在 MEM 级中通过两个流水线寄存器传送给数据存储器。

6. 流水化的基本性能问题

流水化提高了 CPU 指令吞吐量(单位时间内完成的指令数),但并不会缩短单条指令的执行时间。事实上,由于实现流水线的本身控制会产生一定的开销,通常情况下还会在一定程度上延长每条指令的执行时间。虽然说单条指令的运行速度并没有加快,但是吞吐量的增加则意味着程序可以更快的运行,缩短了每条指令的平均执行时间,从而达到总执行时间的缩短。

由于单条指令的执行时间并没有缩短,这实际上限制了流水线的实际深度。除了因为流水线延时产生的据限之外,流水级之间的失衡和流水化开销也会造成限制。流水级之间的不平衡会降低性能,这是因为时钟的运行速度不可能快于最缓慢的流水级。

流水线开销包含流水线寄存器的延时和时钟偏差。流水线寄存器增加了建立时间,即在发出触发写操作的时钟信号之前,寄存器输入必须保持稳定的时间,并且时钟周期的传播也会产生延时。时钟偏差是时钟到达任意两个寄存器时刻之间的最大延时,时钟周期的下限也受此因素的影响。如果时钟周期小于时钟偏差与延时开销之和,那么一个时钟周期中就没有留给有用工作的时间,此时再增加流水线也就没有了意义。

如果流水线中每条指令之间都相互独立没有依赖性,那么这种简单的 RISC 流水线对于证书指令是可以正常运行。但事实上,流水线中的指令很多都是存在相互依赖的关系,这也是导致流水线冒险的一个原因。

觉得这篇文章对你有帮助的话,就留下一个赞吧*^v^*
请尊重作者,转载还请注明出处!感谢配合~
[作者]: Imagine Miracle
[版权]: 本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
[本文链接]: https://blog.csdn.net/qq_36393978/article/details/128848711

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jsp拆迁管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 拆迁管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

java 批量插入千万条数据优化方案【值得收藏】

场景介绍 再实际开发应用中总会面临导入大批量数据插入数据库、数据迁移、同步等操作在java 后台执行&#xff0c;执行效率的优化问题随之而来&#xff01;比如如何快速往MySQL数据库中导入1000万数据 mybatis 2、MySQL中新建一张user表&#xff0c;为了方便演示只保留id、昵称…

【docker】入门

注&#xff1a;最后有面试挑战&#xff0c;看看自己掌握了吗 文章目录docker是什么&#xff1f;Docker Engine overview概述什么是容器container&#xff1f;什么是容器映像 image&#xff1f;官方解释什么是container和container imageDocker objectsImages - 一个用来创建doc…

任务3、监控界面设计

【任务描述】本任务要求使用相对布局或约束布局以及相应的控件完成智慧园区监控系统界面开发一、相对布局&#xff08;RelativeLayout&#xff09;概述相对布局&#xff08;RelativeLayout&#xff09;是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。使用相对布…

Camera Java Native Interface(JNI)介绍

Camera Java Native Interface&#xff08;JNI&#xff09;介绍Java Native Interface&#xff08;JNI&#xff09;概述Our Goal一、JNI启动流程二、Camera JNI 动态注册1.引入库ReferenceblogCode Address:Java Native Interface&#xff08;JNI&#xff09;概述 Android系统…

【软件测试】2023年了还不会接口测试?老鸟总结接口测试面试谁还敢说我不会......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 测试面试&#xff0…

[Java解惑]读书笔记分享

[Java解惑]读书笔记分享 这本书主要讲了Java中经常遇到的坑, 并给出了解释以及解决办法. 读完之后很有收获 读书笔记 表达式之谜 奇数性 用下面的表达式判断一个数是否是奇数 public static boolean isOdd(int i) {return i % 2 1;}问题: 负数无法得出正确的结果. 例如当 i …

建模杂谈系列210 人工智能培训内容梳理

说明 最近打算做一次针对银行的人工智能培训&#xff0c;这里梳理一下培训内容的大纲。以前做过一次很细致的培训&#xff0c;但是现在感觉当时很多文档和内容整理的还是不够方便。 借此机会把这些内容整理好&#xff0c;分门别类放好&#xff0c;争取再有一下次培训的时候可…

嵌入式开发:实时系统中的嵌入式数据库

“实时”这个术语是数据库系统供应商随便说说的&#xff0c;但是实时在嵌入式系统中一直有特定的含义。“实时系统意味着系统是实时的&#xff0c;换句话说&#xff0c;响应应该在指定的时间限制内得到保证&#xff0c;或者系统应该满足指定的期限。例如&#xff0c;飞行控制系…

单目标应用:蜣螂优化算法DBO优化RBF神经网络实现数据预测(提供MATLAB代码)

一、RBF神经网络 1988年&#xff0c;Broomhead和Lowc根据生物神经元具有局部响应这一特点&#xff0c;将RBF引入神经网络设计中&#xff0c;产生了RBF(Radical Basis Function)。1989年&#xff0c;Jackson论证了RBF神经网络对非线性连续函数的一致逼近性能。 RBF的基本思想是…

【面试题】对async/await 的了解?

前言大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库“编程&#xff0c;就像一场开卷考试&#xff0c;题目的答案取决于对书本内容的熟悉程度&#xff1b;而一份源代码就好比一本书&#xff0c…

源码才十几行的数组转换工具arrify,快学起来

前言 前几天在项目中运用到了arrify工具&#xff0c;今天便阅读了arrify的源码&#xff0c;整个源码部分不过才十几行&#xff0c;而且也不难&#xff0c;所以来分享一下阅读心得。 arrify介绍 arrify是什么&#xff0c;有什么作用&#xff0c;或许有些小伙伴还不清楚。简单…

web测试的基本流程

1、web测试流程&#xff1a; (1)web测试 1)参与一个web新项目的测试前&#xff0c;先搜集测试相关的资料&#xff0c;包括原型图、各种需求文档、业务相关等需求相关材料 2)结合第一步搜集到的需求相关资料&#xff0c;自行熟悉系统&#xff0c;同时列出不明白的点&#xff0c;…

时间API在更新,传奇已经谢幕,但技术永远不死

&#xff08;Bill Joy(左一)&#xff0c;Vinod Khosla(左二)&#xff0c;Andy Bechtolsheim(右二)&#xff0c;Scott McNealy(右一) &#xff09; CSDN 博文征集活动&#xff08;和日期相关的代码和bug&#xff09;&#xff1a;点击这里 各位 “big guys”&#xff0c;这篇博文…

植物大战 二叉搜索树——C++

这里是目录标题二叉排序树的概念模拟二叉搜索树定义节点类insert非递归Finderase(重点)析构函数拷贝构造(深拷贝)赋值构造递归FindRInsertR二叉搜索树的应用k模型KV模型二叉排序树的概念 单纯的二叉树存储数据没有太大的作用。 搜索二叉树作用很大。 搜索二叉树的一般都是用…

摸鱼用python获取弹幕的两种方式【前者简单,后者数据好看】

嗨害大家好鸭&#xff01;我是小熊猫~ 相信大家对于 “弹幕文化” 已经相当熟悉啦 你不是一个人在看——这就是弹幕网站的存在感。 它形成了新的“抱团”观看模式&#xff0c; 也真正实现了无时空距离的社交。 有网友表示&#xff0c;弹幕简直比剧情还有趣。 看似简单的寥寥…

【ES】Elasticsearch-深入理解索引原理

文章目录Elasticsearch-深入理解索引原理读操作更新操作SHARD不变性动态更新索引删除和更新实时索引更新持久化Segment合并近实时搜索&#xff0c;段数据刷新&#xff0c;数据可见性更新和事务日志更新索引并且将改动提交修改Searcher对象默认的更新时间Elasticsearch-深入理解…

CentOS8基础篇9:进程的延迟与周期调度

一、进程的概念 进程&#xff1a;开始执行但是还没有结束的程序的实例 程序&#xff1a;包含可执行代码的文件 进程与程序的关系 进程由程序产生&#xff0c;是一个运行着的、要占系统资源的程序 进程不等于程序 浏览网络时&#xff0c;打开多个IE浏览器程序&#xff1b;…

一文讲清楚如何进行主数据编码

主数据编码作为一类重要的数据资源&#xff0c;在信息化建设中具有重要的地位和作用&#xff0c;是保证现有信息系统和未来新系统建设成功的关键因素&#xff0c;决定着系统中的信息一致性。 编码&#xff0c;是一件简单的事情&#xff0c;但绝对不是一件容易做好的事情&#…

FPGA案例开发手册——基于全志T3+Logos FPGA核心板

前 言 本文档主要提供评估板FPGA端案例测试方法,适用的开发环境为Windows 7 64bit和Windows 10 64bit。 本文案例基于创龙科技的全志T3+Logos FPGA核心板,它是一款基于全志科技T3四核ARM Cortex-A7处理器 + 紫光同创Logos PGL25G/PGL50G FPGA设计的异构多核全国产工业核心板…