# 5.5 指令流水线

## 5.5.1 流水线的概念

### 1、指令流水的定义

将指令执行过程划分为<mark style="color:orange;">**不同的阶段**</mark>，占用<mark style="color:orange;">**不同的资源**</mark>，使得多条指令<mark style="color:orange;">**同时执行**</mark>。

#### （1）顺序执行方式

![顺序执行方式](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-c9bf99ccd7c918e7c184c9879904665ad1a54a95%2F%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%E6%96%B9%E5%BC%8F.png?alt=media)

时间：$$T=3nt$$

传统冯诺依曼结构，又称<mark style="color:purple;">**串行执行方式**</mark>。

* 优点
  * 控制简单，硬件代价小
* 缺点
  * 执行指令的速度较慢，
  * 各功能部件的利用率很低

#### （2）一次重叠执行方式

![一次重叠执行方式](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-02f9a944f44aa22bfe9642f375ef518652fe12d7%2F%E4%B8%80%E6%AC%A1%E9%87%8D%E5%8F%A0%E6%89%A7%E8%A1%8C%E6%96%B9%E5%BC%8F.png?alt=media)

时间：$$T=3t+(n-1)\times 2t=(1+2n)t$$

* 优点
  * 程序的执行时间缩短了1/3
  * 各功能部件的利用率明显提高。
* 缺点
  * 需要付出硬件上较大开销的代价
  * 控制过程比顺序执行复杂

#### （3）二次重叠执行方式

![二次重叠执行方式](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-f437956ea671991ee3ce6237fefc601b6210742c%2F%E4%BA%8C%E6%AC%A1%E9%87%8D%E5%8F%A0%E6%89%A7%E8%A1%8C%E6%96%B9%E5%BC%8F.png?alt=media)

时间：$$T=3t+(n-1)t=(2+n)t$$

时间更短

{% hint style="warning" %}
实际使用中也可以分成更多段，如4段甚至5段
{% endhint %}

### 2、流水线的表示方法

#### （1）指令执行过程图

![指令执行过程图](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-f1cd95d3389b2849b3c53c535db07372bfb06ec3%2F%E6%8C%87%E4%BB%A4%E6%89%A7%E8%A1%8C%E8%BF%87%E7%A8%8B%E5%9B%BE.png?alt=media)

主要用于分析指令执行过程以及影响流水线的因素

#### （2）时空图

![时空图](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-31a1b4584a5f8cda4b94986fe862440f01da53c0%2F%E6%97%B6%E7%A9%BA%E5%9B%BE.png?alt=media)

主要用于分析流水线的性能

## 5.5.2 流水线的性能指标

### 1、吞吐率

吞吐率是指在单位时间内流水线所**完成的任务数量**，或是输出结果的数量

* 吞吐率：$$\text{TP}=\frac{n}{T\_{k}}$$
  * $$n$$：任务数量
  * $$T\_{k}$$：完成n个任务的总时间
* 理想状态下的流水线时空图

![流水线的吞吐率](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-a64b88fd6c1a45ab315cbbd2dc784b29d9a558db%2F%E6%B5%81%E6%B0%B4%E7%BA%BF%E7%9A%84%E5%90%9E%E5%90%90%E7%8E%87.png?alt=media)

* 一条指令的执行分为k个阶段
* 每个阶段耗时$$\Delta t$$

$$
\begin{align} \&T\_{k} = \[k+(n-1)]\Delta t\ &\text{TP}=\frac{n}{k+n-1}\Delta t\ &\text{TP}*{max}=\lim*{n \to \infty}\text{TP} = \frac{1}{\Delta t} \end{align}
$$

### 2、加速比

**不使用**流水线所用的时间与**使用**流水线所用的时间之比。

$$
\text{S}*{max} = \lim*{n\to \infty}\text{S}=k
$$

### 3、效率

流水线的<mark style="color:orange;">**设备利用率**</mark>称为流水线的效率。

$$
\begin{align} &流水线效率 =\frac{任务占用了的时空区域}{总的时空区域}\ \ \ &\text{E}*{max} = \lim*{n\to \infty}\text{E}=1 \end{align}
$$

## 5.5.3 影响流水线的因素

### 1、结构相关（资源冲突）

**结构相关**：由于多条指令在同一时刻<mark style="color:orange;">**争用同一资源**</mark>（主存、寄存器等）而形成的冲突

#### 解决方案

* 后一相关指令暂停一周期
* **资源重复配置**：数据存储器+指令存储器分开存储

### 2、数据相关（数据冲突）

在一个程序中，存在必须<mark style="color:orange;">**等待**</mark>前一条指令执行完才能执行后一条指令的情况，则这两条指令即为<mark style="color:purple;">**数据相关**</mark>。

#### 解决方案

* 把遇到数据相关的指令及其后续指令都暂停一至几个时钟周期，直到数据相关问题消失后再继续执行
  * 硬件阻塞（stall）
  * 软件插入<mark style="color:purple;">**空操作NOP**</mark>
* **数据旁路**技术：通过数据旁路直接将ALU的运算结果接回为下一条操作的输入
* **编译优化**：通过编译器调整指令顺序来解决数据相关

### 3、控制相关（控制冲突）

当流水线遇到<mark style="color:purple;">**转移指令**</mark>和其他<mark style="color:orange;">**改变PC值**</mark>的指令而造成断流时，会引起控制相关

#### 解决方案

* 转移指令分支预测
  * 简单预测
  * 动态预测
* 预取转移成功和不成功两个控制流方向上的目标指令
* 加快和提前形成条件码
* 提高转移方向的猜准率
* 在分支指令插入空操作

## 5.5.4 流水线的分类

### 1、根据流水线使用的级别

* **部件功能级流水线**：将复杂的<mark style="color:purple;">**算术逻辑运算**</mark>组成流水线工作方式
* **处理机级流水线**：把一条<mark style="color:purple;">**指令**</mark>解释过程分成多个子过程
* **处理机间级流水线**：协调不同处理机间的不同任务

### 2、根据流水线可以完成的功能

* **单功能流水线**：只能实现一种固定的专门功能
* **多功能流水线**：通过各段间的不同连接方式可以同时或不同时地实现多种功能

### 3、根据同一时间内各段之间的连接方式

* **静态流水线**：在同一时间内，流水线的各段只能按同一种功能的连接方式工作
* **动态流水线**：在同一时间内，当某些段正在实现某种运算时，另一些段可以进行另一种运算

### 4、根据各个功能段之间是否有反馈信号

* **线性流水线**：从输入到输出，每个功能段<mark style="color:orange;">**只允许经过一次**</mark>， 不存在反馈回路
* **非线性流水线**：存在反馈回路，从输入到输出过程中，某些功能段将数次通过流水线，这种流水线适合进行线性递归的运算

## 5.5.5 流水线的多发技术

### 1、超标量技术

![超标量技术](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-787f3515c5b536ebeb67ecc6ba8b34122012704a%2F%E8%B6%85%E6%A0%87%E9%87%8F%E6%8A%80%E6%9C%AF.png?alt=media)

每个时钟周期内可<mark style="color:orange;">**并发多条独立指令**</mark>，通过编译优化技术，把可并行执行的指令搭配起来。属于<mark style="color:orange;">**空分复用技术**</mark>。

* 要配置多个功能部件
* 不能调整指令的执行顺序
* 如上图中，称为处理机的<mark style="color:orange;">**度为3**</mark>
  * 传统指令流水线度为1

### 2、超流水技术

![超流水技术](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-0ce4a9926f577b961ee5c5c81a1e2ce9df71b71b%2F%E8%B6%85%E6%B5%81%E6%B0%B4%E6%8A%80%E6%9C%AF.png?alt=media)

在一个时钟周期内<mark style="color:orange;">**再分段**</mark>，一个功能部件使用多次。属于<mark style="color:orange;">**时分复用技术**</mark>。

* 流水线速度为原来的多倍
* 不能调整指令的执行顺序
* 靠编译程序解决优化问题

### 3、超长指令字

![超长指令字](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-de900f6cdaff4cabea057286dd5503f98c37a3d2%2F%E8%B6%85%E9%95%BF%E6%8C%87%E4%BB%A4%E5%AD%97.png?alt=media)

由编译程序挖掘出指令间潜在的并行性，将多条能并行操作的指令组合成一条

* 具有多个操作码字段的超长指令字（可达几百位）

## 5.5.6 5段式指令流水线

![5段式流水线](https://263180029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MgTVRt7hyq7APa35yqR%2Fuploads%2Fgit-blob-cf1c5b1314ad22dfa7c9008c720f128da29c743c%2F5%E6%AE%B5%E5%BC%8F%E6%B5%81%E6%B0%B4%E7%BA%BF.png?alt=media)

* **取指IF**（instruction fetch）：将指令从Cache中取出，放入寄存器
* **指令译码ID**（instruction decode）
  * 指令译码
  * 将操作数从通用寄存器中取出，放入锁存器
* **执行EX**（execute）
* **访存M**（memory）
* **写回WB**（write back）：将运算结果写回主存/寄存器

{% hint style="warning" %}
指令和数据分开存储在两个Cache中，可以使得取指与访存同时执行

Cache未命中会造成流水线断流

RISC中只有LOAD和STORE指令才能访问主存
{% endhint %}

令每个阶段时间耗时一样，取最长耗时为准

**缓冲寄存器（锁存器）**：位于流水线每一段之后，其作用是<mark style="color:orange;">**保存本流水段的执行结果**</mark>，提供给下一流水段使用

### 1、运算类指令

```
add Rs,Rd
```

* IF：根据PC从指令Cache取指令到IF段锁存
* ID：取出操作数到ID段锁存
* EX：运算，将结果存入EX段锁存
* M：空段
* WB：将运算结果写回指定寄存器

### 2、LOAD指令

```
LOAD Rd,114(Rs)
```

* IF：根据PC从指令Cache取指令到IF段锁存
* ID
  * 将<mark style="color:purple;">**基址寄存器**</mark>的值存到段锁存器中
  * 将<mark style="color:purple;">**偏移量**</mark>的值（立即数）存到Imm中
* EX：运算，得到有效地址，将结果存入EX段锁存
* M：根据有效地址从Cache中取数，放入M段锁存器中
* WB：将取出的数写回指定寄存器

### 3、STORE指令

```
STORE Rs,114(Rd)
```

* IF：根据PC从指令Cache取指令到IF段锁存
* ID
  * 将<mark style="color:purple;">**基址寄存器**</mark>的值存到ID段锁存器中
  * 将<mark style="color:purple;">**偏移量**</mark>的值（立即数）存到Imm中
  * 将要存的数放到ID段锁存器中
* EX：
  * 运算，得到有效地址，将结果存入EX段锁存
  * 将要存的数从ID段锁存器转移到EX段锁存
* M：将数据写入Cache
* WB：空段

### 4、转移类指令

```
beq Rs,Rt,#114 //若(Rs)==(Rt),则(PC)+指令字长+(偏移量X指令字长)→PC
```

* IF：根据PC从指令Cache取指令到IF段锁存
* ID
  * 将要进行比较的两个数存到段锁存器中
  * 将<mark style="color:purple;">**偏移量**</mark>的值（立即数）存到Imm中
* EX：运算，比较两个数
* M：将目标PC的值写回PC
* WB：空段

### 5、无条件转移指令

```
jmp #114
```

* IF：根据PC从指令Cache取指令到IF段锁存
* ID：将<mark style="color:purple;">**偏移量**</mark>的值（立即数）存到Imm中
* EX：将目标PC的值写回PC
* M：空段
* WB：空段

{% hint style="warning" %}
修改PC的硬件实际上是与5段式流水线的硬件独立的

需要尽早的完成对PC的修改
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://aye10032.gitbook.io/computerorganizationnote/di-wu-zhang-zhong-yang-chu-li-qi/5.5-zhi-ling-liu-shui-xian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
