152 lines
6.8 KiB
Markdown
152 lines
6.8 KiB
Markdown
---
|
||
tags:
|
||
- 计算机系统结构
|
||
- 重点复习
|
||
- 流水线
|
||
- 控制冲突
|
||
create time: 2026-06-16 21:21
|
||
---
|
||
|
||
# 小题 3 — 控制冲突的解决措施
|
||
|
||
## 概述
|
||
|
||
本题考查流水线中**控制冲突**(Control Hazard)的概念,以及为**减少分支指令引起的延迟**所采取的有效措施。控制冲突是流水线三大冲突之一,理解其解决方案对理解现代处理器设计至关重要。
|
||
|
||
> [!tip] 考试重点
|
||
> 重点掌握三大类解决措施:**暂停**、**预测**、**延迟分支**。其中延迟分支的"延迟槽"概念和分支预测的基本原理是常考知识点。
|
||
|
||
## 正文
|
||
|
||
### 一、什么是控制冲突?
|
||
|
||
**控制冲突**(Control Hazard)是由**分支指令**(如 if-else、循环跳转)引起的。当处理器执行分支指令时,需要等到分支结果确定后才能知道下一条应该取哪里的指令。但在等待期间,流水线已经预取了后续指令——如果预测错误,这些预取的指令就必须作废。
|
||
|
||
```mermaid
|
||
graph LR
|
||
A["Branch Instruction"] --> B{"Branch Taken?"}
|
||
B -- "Yes" --> C["Target Address"]
|
||
B -- "No" --> D["PC + 4 (Next)"]
|
||
|
||
style B fill:#ff9800
|
||
```
|
||
|
||
> [!question] 控制冲突的代价有多大?
|
||
> 假设分支指令在 EX 段(第 3 段)确定结果,那么在 5 段流水线中,分支指令后面有 2 条指令已经被取入流水线。如果分支跳转了,这 2 条指令就要作废——浪费 2 个时钟周期。对于深度流水线(如 15~20 段),分支延迟更大。
|
||
|
||
### 二、解决措施总览
|
||
|
||
| 措施 | 原理 | 性能收益 | 硬件开销 |
|
||
|------|------|:--------:|:--------:|
|
||
| **暂停(Stall)** | 等待分支结果确定后再取指 | 无(性能最差) | 无 |
|
||
| **预测(Predict)** | 猜测分支方向,提前取指 | 高(预测准确时) | 中~高 |
|
||
| **延迟分支(Delayed Branch)** | 分支指令后的延迟槽总被执行 | 中等 | 低 |
|
||
|
||
### 三、措施详解
|
||
|
||
#### 3.1 暂停(Stall)
|
||
|
||
最简单的方法:分支指令进入流水线后,**暂停**后续指令的取指,直到分支结果确定。
|
||
|
||
- **优点**:实现最简单,零硬件开销
|
||
- **缺点**:性能损失严重。对于 $k$ 段流水线,分支在第 $m$ 段确定结果时,浪费 $m-1$ 个时钟周期
|
||
|
||
> [!warning] 为什么暂停不可接受?
|
||
> 分支指令在程序中占比约 15%~25%。如果每条分支指令都暂停 2~3 拍,流水线效率将下降 30%~75%。这就是为什么必须采用预测技术。
|
||
|
||
#### 3.2 分支预测(Branch Prediction)
|
||
|
||
在分支结果确定之前,**预测**分支方向并提前取指。预测分为两大类:
|
||
|
||
| 预测类型 | 方法 | 预测准确率 | 硬件复杂度 |
|
||
|----------|------|:----------:|:----------:|
|
||
| **静态预测** | 编译时确定,运行时不变 | 60%~70% | 低 |
|
||
| **动态预测** | 运行时根据历史信息动态调整 | 90%~95% | 高 |
|
||
|
||
**静态预测的常见策略**:
|
||
|
||
| 策略 | 预测行为 | 适用场景 |
|
||
|------|----------|----------|
|
||
| 总是预测不跳转 | 分支不发生,继续顺序取指 | 循环体外的分支 |
|
||
| 总是预测跳转 | 分支发生,跳转到目标地址 | 循环体内的分支(循环通常继续) |
|
||
| 根据分支方向预测 | 向后跳转预测为跳转(循环),向前跳转预测为不跳转 | 通用场景 |
|
||
| 由编译器标注 | 编译器在分支指令中设置预测位 | Profile-guided 优化 |
|
||
|
||
**动态预测的常见策略**:
|
||
|
||
| 策略 | 原理 | 状态数 |
|
||
|------|------|:------:|
|
||
| 1 位预测器 | 记录上次分支结果 | 2 |
|
||
| 2 位饱和计数器 | 需要连续 2 次预测错误才改变方向 | 4 |
|
||
| 相关预测器 | 参考其他分支的历史 | 4+ |
|
||
| 锦标赛预测器 | 多个预测器投票 | 多 |
|
||
|
||
```mermaid
|
||
stateDiagram-v2
|
||
[*] --> StronglyNotTaken
|
||
StronglyNotTaken --> WeaklyNotTaken: "Taken"
|
||
WeaklyNotTaken --> WeaklyTaken: "Taken"
|
||
WeaklyTaken --> StronglyTaken: "Taken"
|
||
StronglyTaken --> WeaklyTaken: "Not Taken"
|
||
WeaklyTaken --> WeaklyNotTaken: "Not Taken"
|
||
WeaklyNotTaken --> StronglyNotTaken: "Not Taken"
|
||
```
|
||
|
||
> [!note] 2 位饱和计数器的工作原理
|
||
> 2 位饱和计数器是最经典的动态预测方案:
|
||
> - **4 个状态**:强不跳转(00)、弱不跳转(01)、弱跳转(10)、强跳转(11)
|
||
> - **预测规则**:高位为 1 预测跳转,高位为 0 预测不跳转
|
||
> - **更新规则**:分支跳转时计数器+1(饱和),不跳转时-1(饱和)
|
||
> - **优势**:偶发的方向改变不会立即改变预测(需要连续 2 次才翻转),适合循环场景
|
||
|
||
#### 3.3 延迟分支(Delayed Branch)
|
||
|
||
**核心思想**:编译器将分支指令后面的一条指令定义为**延迟槽**(Delay Slot),延迟槽中的指令**无论分支是否跳转都会被执行**。
|
||
|
||
```
|
||
BEQ R1, R2, TARGET ; 分支指令
|
||
ADD R3, R4, R5 ; 延迟槽:总被执行
|
||
SUB R6, R7, R8 ; 分支目标(如果跳转)
|
||
```
|
||
|
||
编译器的任务是找到一条**安全的、有用的**指令填入延迟槽:
|
||
|
||
| 填充策略 | 方法 | 效果 |
|
||
|----------|------|------|
|
||
| 从前调度 | 将分支指令**前面**的独立指令移入延迟槽 | 最常用 |
|
||
| 从目标调度 | 将分支目标处的指令复制到延迟槽 | 适用于循环 |
|
||
| 从失败路径调度 | 将分支不跳转时的下一条指令移入延迟槽 | 适用于 if-else |
|
||
| 填充 NOP | 找不到合适指令时填空操作 | 无收益但保证正确性 |
|
||
|
||
> [!question] 思考:延迟分支有什么局限?
|
||
> 1. 只能补偿**1 拍**的分支延迟(延迟槽只有 1 条指令的空间)
|
||
> 2. 对于深度流水线(延迟 2~3 拍),延迟分支**力不从心**
|
||
> 3. 需要编译器配合,增加了编译器设计的复杂度
|
||
>
|
||
> 因此现代深度流水线处理器主要依靠**动态分支预测**,延迟分支主要用于简单 RISC 处理器。
|
||
|
||
### 四、三种措施的对比
|
||
|
||
| 对比维度 | 暂停 | 分支预测 | 延迟分支 |
|
||
|----------|:----:|:--------:|:--------:|
|
||
| 性能 | 最差 | 最好 | 中等 |
|
||
| 硬件开销 | 无 | 中~高 | 低 |
|
||
| 需要编译器支持 | 否 | 否 | 是 |
|
||
| 适用流水线深度 | 浅 | 深/浅均可 | 浅(1~2 拍延迟) |
|
||
| 预测错误时的处理 | 不需要 | 需要冲刷流水线 | 不需要 |
|
||
| 现代处理器使用 | 仅作后备 | **主要手段** | 辅助手段 |
|
||
|
||
> [!abstract]- 答案
|
||
> 为减少分支指令引起的控制冲突延迟,采取的有效措施包括:
|
||
>
|
||
> **(1)暂停**:等待分支结果确定后再取指,简单但性能最差。
|
||
>
|
||
> **(2)分支预测**:静态预测(预测不跳转/预测跳转)和动态预测(1 位/2 位饱和计数器、相关预测器)。
|
||
>
|
||
> **(3)延迟分支**:编译器在分支指令后的延迟槽中填入必定执行的指令。
|
||
|
||
## 关联笔记
|
||
- [[计算机系统结构/复习文档/流水线技术]]
|
||
- [[小题2-流水线的分类]]
|
||
- [[小题4-流水寄存器的作用]]
|