vault backup: 2026-06-15 22:55:55
This commit is contained in:
+125
-4
@@ -10,10 +10,10 @@ create time: 2026-06-15 10:00
|
||||
|
||||
## 概述
|
||||
|
||||
本文档讲解多处理器系统的基本概念、存储一致性模型、通信开销分析以及并行系统性能评估。多处理器和并行处理是现代计算机系统结构的重要方向,涉及软硬件协同设计的多个层面。
|
||||
本文档讲解多处理器系统的基本概念与分类、存储一致性模型(MSI 协议状态转移)、共享内存与分布式内存的架构对比,以及并行系统性能评估——包括远程访问 CPI 分析、计算/通信比、Amdahl 定律在并行系统中的应用。多处理器和并行处理是现代计算机系统结构的重要方向,涉及软硬件协同设计的多个层面。
|
||||
|
||||
> [!tip] 考试重点
|
||||
> 存储一致性的三个条件是论述题高频考点。远程访问对并行系统性能影响的计算(CPI 分析)在综合题中出现。
|
||||
> 存储一致性的三个条件是论述题高频考点。MSI 协议状态转移图常以简答题出现。远程访问 CPI 分析、Amdahl 定律的并行扩展在综合题中反复出现。
|
||||
|
||||
## 正文
|
||||
|
||||
@@ -37,6 +37,36 @@ create time: 2026-06-15 10:00
|
||||
| 适用场景 | 规则的数据并行(矩阵运算) | 不规则的并行任务 |
|
||||
| 灵活性 | 低(需同步) | 高(独立执行) |
|
||||
|
||||
#### 1.3 共享内存 vs 分布式内存
|
||||
|
||||
多处理器系统和多计算机系统的核心区别在于内存架构:
|
||||
|
||||
| 对比维度 | 共享内存多处理器(SMP/NUMA) | 分布式内存多计算机(MPP/Cluster) |
|
||||
|----------|---------------------------|----------------------------------|
|
||||
| **内存视图** | 所有处理器看到统一的地址空间 | 每个节点有独立的本地内存 |
|
||||
| **通信方式** | 通过 Load/Store 指令直接访问共享变量 | 通过消息传递(MPI)交换数据 |
|
||||
| **编程模型** | 共享变量 + 锁/信号量 | 消息传递(Send/Receive) |
|
||||
| **数据一致性** | 需要硬件一致性协议(如 MSI) | 由程序员显式管理 |
|
||||
| **可扩展性** | 受限于内存互连带宽,通常 < 64 处理器 | 可扩展到数千节点 |
|
||||
| **编程难度** | 较低(共享地址空间) | 较高(需显式管理数据分布) |
|
||||
| **典型代表** | 大型服务器(SMP)、NUMA 服务器 | 超算集群(如 Summit) |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph SMP["共享内存多处理器"]
|
||||
P1["处理器 1"] --> SM["共享内存"]
|
||||
P2["处理器 2"] --> SM
|
||||
P3["处理器 3"] --> SM
|
||||
end
|
||||
subgraph MPP["分布式内存多计算机"]
|
||||
N1["节点 1: CPU + 本地内存"] <-->|"消息传递"| N2["节点 2: CPU + 本地内存"]
|
||||
N2 <-->|"消息传递"| N3["节点 3: CPU + 本地内存"]
|
||||
end
|
||||
```
|
||||
|
||||
> [!question] 思考
|
||||
> 为什么共享内存系统难以扩展到大规模?因为所有处理器竞争同一个内存系统的带宽。当处理器数量增加时,内存带宽成为瓶颈。NUMA(非统一内存访问)架构通过让每个处理器有本地内存来缓解,但远程访问延迟仍然远高于本地访问。
|
||||
|
||||
### 二、存储一致性(Cache Coherence)
|
||||
|
||||
#### 2.1 问题背景
|
||||
@@ -76,6 +106,28 @@ create time: 2026-06-15 10:00
|
||||
| **S**(Shared) | 该行未被修改,多个 Cache 可能有副本 |
|
||||
| **I**(Invalid) | 该行无效 |
|
||||
|
||||
**MSI 协议状态转移图**:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> I
|
||||
I --> M: "本地写 (Local Write)"
|
||||
I --> S: "本地读命中 (Local Read Hit)"
|
||||
S --> M: "本地写 (Local Write)"
|
||||
M --> S: "远程读 (Remote Read, 总线读命中)"
|
||||
M --> I: "远程写 (Remote Write, 总线写命中)"
|
||||
S --> I: "远程写 (Remote Write, 总线写命中)"
|
||||
I --> I: "远程写 (Remote Write, 监听到写)"
|
||||
```
|
||||
|
||||
> [!note] 状态转移详解
|
||||
> - **本地操作**(本处理器发起):读命中时从 S 转移或保持 S;写操作将状态提升为 M(独占且已修改)。
|
||||
> - **远程操作**(其他处理器通过总线发起):当某处理器写数据时,其他持有该数据副本的 Cache 必须将其置为 I(无效);当某处理器读数据时,持有 M 状态的 Cache 需先将数据写回主存并将自身降为 S。
|
||||
> - **M -> S 的"写回"**:当远程处理器读取数据时,持有 M 状态的 Cache 必须先将修改的数据写回主存,然后转为 S。这保证了数据一致性。
|
||||
|
||||
> [!question] 思考
|
||||
> 为什么需要 M 状态?直接用 S 和 I 不行吗?如果只有 S 和 I,每次写操作都需要立即写回主存(write-through),这会导致大量总线流量。M 状态允许延迟写回(write-back),只有在其他处理器需要读该数据时才写回,大大减少了总线通信量。
|
||||
|
||||
> [!question] 监听协议为什么不适合大规模系统?
|
||||
> 监听协议要求所有 Cache 监听总线,总线带宽成为瓶颈。当处理器数量增加时,总线冲突急剧增加,监听协议的可扩展性很差。目录协议通过点对点通信避免了这个问题。
|
||||
|
||||
@@ -89,7 +141,7 @@ create time: 2026-06-15 10:00
|
||||
|
||||
$$CPI = CPI_{base} + \text{远程访问率} \times \text{远程访问延迟(时钟数)}$$
|
||||
|
||||
> [!example] 远程访问性能影响
|
||||
> [!example] 例题 1:远程访问性能影响
|
||||
> 32 个处理器的集群,本地执行时间 10ns,CPI = 1.0。若有 0.5% 指令需远程访问(2000ns):
|
||||
>
|
||||
> 远程访问时钟 $= 2000 / 10 = 200$
|
||||
@@ -98,6 +150,20 @@ $$CPI = CPI_{base} + \text{远程访问率} \times \text{远程访问延迟(
|
||||
>
|
||||
> **结论**:0.5% 的远程访问使 CPI 翻倍,性能下降 50%。
|
||||
|
||||
> [!example] 例题 2:不同远程访问率的对比分析
|
||||
> 假设有 16 个处理器的 NUMA 系统,基本 CPI = 1.2,时钟周期 2ns,本地内存访问 40ns,远程内存访问 200ns。
|
||||
>
|
||||
> | 场景 | 远程访问率 | 远程延迟(时钟) | 有效 CPI | 相对性能 |
|
||||
> |------|:---------:|:-------------:|:--------:|:-------:|
|
||||
> | 优化的并行程序 | 1% | 100 | $1.2 + 0.01 \times 100 = 2.2$ | 1.00 |
|
||||
> | 一般并行程序 | 5% | 100 | $1.2 + 0.05 \times 100 = 6.2$ | 0.35 |
|
||||
> | 通信密集程序 | 10% | 100 | $1.2 + 0.10 \times 100 = 11.2$ | 0.20 |
|
||||
>
|
||||
> **分析**:远程访问率从 1% 增加到 10%,CPI 从 2.2 飙升到 11.2,性能下降到原来的 1/5。这说明**数据局部性**对并行系统性能至关重要。优化并行程序的核心任务之一就是最小化远程访问比例。
|
||||
|
||||
> [!question] 思考
|
||||
> 如果远程内存访问延迟从 200ns 优化到 100ns(比如使用更快的互连网络),对通信密集程序(10% 远程访问率)的 CPI 影响有多大?新的 CPI = 1.2 + 0.10 * 50 = 6.2,相比原来的 11.2 几乎减半。硬件改进(降低远程延迟)和软件优化(减少远程访问率)同等重要。
|
||||
|
||||
#### 3.2 并行计算的挑战
|
||||
|
||||
| 挑战 | 说明 | 应对方法 |
|
||||
@@ -106,13 +172,68 @@ $$CPI = CPI_{base} + \text{远程访问率} \times \text{远程访问延迟(
|
||||
| **通信开销** | 处理器间数据交换的延迟 | 优化通信模式、减少同步 |
|
||||
| **负载不均衡** | 各处理器工作量不等 | 动态调度、任务细分 |
|
||||
|
||||
#### 3.3 计算/通信比
|
||||
#### 3.3 Amdahl 定律在并行系统中的应用
|
||||
|
||||
Amdahl 定律指出,程序的加速比受限于串行部分的比例:
|
||||
|
||||
$$S = \frac{1}{(1 - f) + \frac{f}{P}}$$
|
||||
|
||||
其中 $f$ 为可并行化的比例,$P$ 为处理器数量。
|
||||
|
||||
> [!example] 例题:Amdahl 定律计算
|
||||
> 某程序总执行时间中,串行部分占 10%($f = 0.9$)。
|
||||
>
|
||||
> | 处理器数 $P$ | 加速比 $S$ | 效率 $S/P$ | 边际收益 |
|
||||
> |:-----------:|:---------:|:---------:|:--------:|
|
||||
> | 1 | 1.00 | 100% | - |
|
||||
> | 2 | 1.82 | 91% | 0.82 |
|
||||
> | 4 | 3.08 | 77% | 1.26 |
|
||||
> | 8 | 4.71 | 59% | 1.63 |
|
||||
> | 16 | 6.40 | 40% | 1.69 |
|
||||
> | 32 | 7.80 | 24% | 1.40 |
|
||||
> | 64 | 8.77 | 14% | 0.97 |
|
||||
> | $\infty$ | 10.00 | 0% | - |
|
||||
>
|
||||
> **计算过程**(以 $P = 8$ 为例):
|
||||
>
|
||||
> $S = \frac{1}{0.1 + 0.9/8} = \frac{1}{0.1 + 0.1125} = \frac{1}{0.2125} \approx 4.71$
|
||||
>
|
||||
> **关键发现**:
|
||||
>
|
||||
> 1. **理论上限**:即使无限处理器,加速比也不会超过 $1/0.1 = 10$ 倍。这就是串行瓶颈。
|
||||
> 2. **边际收益递减**:从 16 个到 32 个处理器,只增加了 1.4 倍加速比(边际收益列)。处理器翻倍,收益远小于翻倍。
|
||||
> 3. **效率下降**:处理器越多,每个处理器的利用率越低。
|
||||
|
||||
> [!important] Amdahl 定律的实践启示
|
||||
> - 与其追求更多处理器,不如先优化串行部分。将串行比例从 10% 降到 5%,理论上限从 10 倍提升到 20 倍。
|
||||
> - 在实际系统中,通信开销进一步拉低并行效率。真正有效的加速比远低于 Amdahl 定律的预测。
|
||||
> - 这就是为什么"弱扩展"(增大问题规模以保持效率)比"强扩展"(固定问题规模增加处理器)在实践中更有意义。
|
||||
|
||||
#### 3.4 计算/通信比
|
||||
|
||||
$$\text{计算/通信比} = \frac{\text{计算量}}{\text{通信量}}$$
|
||||
|
||||
- 随数据规模增加而**增大**(计算量增长快于通信量)
|
||||
- 随处理器数目增加而**减小**(每个处理器分到的计算减少,但通信开销相对增加)
|
||||
|
||||
> [!example] 例题:计算/通信比的趋势分析
|
||||
> 一个矩阵乘法问题,矩阵规模为 $N \times N$,使用 $P$ 个处理器并行计算。
|
||||
>
|
||||
> - 计算量:$O(N^3 / P)$(每个处理器分担的计算)
|
||||
> - 通信量:$O(N^2 / \sqrt{P})$(2D 分块方案下的通信开销)
|
||||
> - 计算/通信比:$O(N^3 / P) \div O(N^2 / \sqrt{P}) = O(N / \sqrt{P})$
|
||||
>
|
||||
> **趋势演示**(设 $N = 1000$, $P = 16$):
|
||||
>
|
||||
> | 参数变化 | 计算量(相对) | 通信量(相对) | 计算/通信比 |
|
||||
> |----------|:-----------:|:-----------:|:----------:|
|
||||
> | $N=1000, P=16$ | 62.5 | 250 | 0.25 |
|
||||
> | $N=2000, P=16$ | 500 | 500 | 1.00 |
|
||||
> | $N=4000, P=16$ | 4000 | 1000 | 4.00 |
|
||||
> | $N=2000, P=64$ | 125 | 250 | 0.50 |
|
||||
>
|
||||
> **结论**:规模翻倍(1000→2000→4000),计算/通信比快速提升(0.25→1→4),而增加处理器(16→64)则计算/通信比下降(1→0.5)。这就是为什么"规模化并行"(scaling up the problem)比"增加处理器"更能提高并行效率。
|
||||
|
||||
> [!tip] 提高并行效率的关键
|
||||
> 尽量提高计算/通信比:增大问题规模、优化通信模式(减少全局通信)、使用高带宽低延迟的互连网络。
|
||||
|
||||
|
||||
+197
-9
@@ -57,6 +57,57 @@ graph TD
|
||||
> [!note] 组相联 Cache 的命名
|
||||
> "$n$ 路组相联"表示每组有 $n$ 个 Cache 行。2 路组相联 = 每组 2 行,4 路组相联 = 每组 4 行。
|
||||
|
||||
**地址解析格式**:
|
||||
|
||||
处理器发出的地址需要被拆分为 Tag / Index / Offset 三部分,不同映像方式的拆分规则不同:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "直接映像地址"
|
||||
A1["Tag"] --- A2["Index"] --- A3["Block Offset"]
|
||||
end
|
||||
subgraph "全相联地址"
|
||||
B1["Tag"] --- B2["Block Offset"]
|
||||
end
|
||||
subgraph "组相联地址"
|
||||
C1["Tag"] --- C2["Set Index"] --- C3["Block Offset"]
|
||||
end
|
||||
```
|
||||
|
||||
各字段含义:
|
||||
|
||||
| 字段 | 含义 | 位数计算 |
|
||||
|------|------|----------|
|
||||
| **Block Offset** | 块内偏移,定位块中具体哪个字节 | $\log_2(\text{块大小})$ |
|
||||
| **Index**(直接映像) | 定位 Cache 中的哪一行 | $\log_2(\text{Cache 行数})$ |
|
||||
| **Set Index**(组相联) | 定位 Cache 中的哪一组 | $\log_2(\text{组数})$ |
|
||||
| **Tag** | 标记位,用于比对确认是否命中 | 地址总位数 - Index位数 - Offset位数 |
|
||||
|
||||
> [!example] 地址位分解示例
|
||||
>
|
||||
> **已知**:32 位地址,Cache 容量 16KB,块大小 64B,采用 4 路组相联。
|
||||
>
|
||||
> **计算各字段位数**:
|
||||
>
|
||||
> - Offset 位数 = $\log_2(64) = 6$ 位
|
||||
> - Cache 行数 = $16\text{KB} / 64\text{B} = 256$ 行
|
||||
> - 组数 = $256 / 4 = 64$ 组
|
||||
> - Set Index 位数 = $\log_2(64) = 6$ 位
|
||||
> - Tag 位数 = $32 - 6 - 6 = 20$ 位
|
||||
>
|
||||
> **地址 `0x1A2B3C47` 的解析**:
|
||||
>
|
||||
> | 字段 | 位数 | 二进制值 |
|
||||
> |:----:|:----:|:---------|
|
||||
> | Tag(高 20 位) | 31~12 | `0001 1010 0010 1011 0011` |
|
||||
> | Set Index(6 位) | 11~6 | `110001` = 第 49 组 |
|
||||
> | Offset(6 位) | 5~0 | `000111` = 块内第 7 字节 |
|
||||
>
|
||||
> > [!question] 如果改成直接映像呢?
|
||||
> > 直接映像:Index = $\log_2(256) = 8$ 位,Tag = $32 - 8 - 6 = 18$ 位。
|
||||
> > 同一地址会映射到第 `10010001` = 第 145 行,而不是第 49 组的某一行。
|
||||
> > 相联度越高,Index 位数越少,Tag 位数越多,硬件比对逻辑越复杂。
|
||||
|
||||
#### 2.2 替换策略
|
||||
|
||||
| 策略 | 原理 | 特点 |
|
||||
@@ -80,22 +131,78 @@ $$\text{不命中率} = w_I \times mr_I + w_D \times mr_D$$
|
||||
|
||||
其中 $w_I$、$w_D$ 分别为指令和数据的访问占比,$mr_I$、$mr_D$ 为各自的不命中率。
|
||||
|
||||
> [!example] 完整例题:地址序列命中/不命中判断
|
||||
>
|
||||
> **已知**:直接映像 Cache,4 行,块大小 16B(4 个字,每字 4B)。地址按字节编址。
|
||||
>
|
||||
> 地址结构:`[ Tag(高位) | Index(2位) | Offset(4位) ]`
|
||||
>
|
||||
> - Index 位数 = $\log_2(4) = 2$ 位(4 行直接映像)
|
||||
> - Offset 位数 = $\log_2(16) = 4$ 位(块大小 16B)
|
||||
>
|
||||
> **访问以下地址序列**(十进制,假设地址按字节编址):
|
||||
>
|
||||
> | 序号 | 地址(十进制) | 地址(二进制) | Tag | Index | Offset | 块号 | 行号 | 结果 |
|
||||
> |:----:|:-------------:|:--------------:|:---:|:-----:|:------:|:----:|:----:|:----:|
|
||||
> | 1 | 0 | `00000000` | 0 | 00 | 0000 | 0 | 0 | **不命中**(冷启动) |
|
||||
> | 2 | 4 | `00000100` | 0 | 00 | 0100 | 0 | 0 | **命中**(同一块) |
|
||||
> | 3 | 16 | `00010000` | 0 | 01 | 0000 | 1 | 1 | **不命中**(新行) |
|
||||
> | 4 | 132 | `10000100` | 8 | 01 | 0100 | 8 | 1 | **不命中**(替换行 1) |
|
||||
> | 5 | 136 | `10001000` | 8 | 01 | 1000 | 8 | 1 | **命中**(同一块) |
|
||||
> | 6 | 64 | `01000000` | 4 | 00 | 0000 | 4 | 0 | **不命中**(替换行 0) |
|
||||
> | 7 | 48 | `00110000` | 3 | 00 | 0000 | 3 | 0 | **不命中**(替换行 0) |
|
||||
> | 8 | 64 | `01000000` | 4 | 00 | 0000 | 4 | 0 | **不命中**(已被替换) |
|
||||
>
|
||||
> **Cache 行状态变化**:
|
||||
>
|
||||
> | 步骤 | 行 0 | 行 1 | 行 2 | 行 3 |
|
||||
> |:----:|:----:|:----:|:----:|:----:|
|
||||
> | 初始 | 空 | 空 | 空 | 空 |
|
||||
> | 访问 0 | Tag=0 | 空 | 空 | 空 |
|
||||
> | 访问 4 | Tag=0 | 空 | 空 | 空 |
|
||||
> | 访问 16 | Tag=0 | Tag=0 | 空 | 空 |
|
||||
> | 访问 132 | Tag=0 | **Tag=8** | 空 | 空 |
|
||||
> | 访问 64 | **Tag=4** | Tag=8 | 空 | 空 |
|
||||
> | 访问 48 | **Tag=3** | Tag=8 | 空 | 空 |
|
||||
> | 访问 64 | **Tag=4** | Tag=8 | 空 | 空 |
|
||||
>
|
||||
> 命中率 = $2/8 = 25\%$
|
||||
>
|
||||
> > [!question] 观察到了什么?
|
||||
> > 地址 64 在第 6 次访问时被调入,但第 7 次访问 48 时将它替换出,导致第 8 次再次访问 64 时又不命中——这就是典型的**颠簸(Thrashing)**现象。解决方法:提高相联度或增大 Cache 容量。
|
||||
|
||||
#### 3.2 平均访存时间
|
||||
|
||||
$$\text{平均访存时间} = \text{命中时间} + \text{不命中率} \times \text{不命中开销}$$
|
||||
|
||||
> [!example] 分离 Cache vs 混合 Cache
|
||||
> [!example] 分离 Cache vs 混合 Cache(详解)
|
||||
>
|
||||
> **分离 Cache**(指令 16KB + 数据 16KB):
|
||||
> - 指令不命中率 1%,数据不命中率 5%
|
||||
> - 命中时间均为 1 周期,不命中开销 40 周期
|
||||
> - 平均访存时间 $= 78\% \times (1 + 1\% \times 40) + 22\% \times (1 + 5\% \times 40) = 1.752$ 周期
|
||||
> **已知条件**:
|
||||
> - 程序中 78% 是指令访问(取指),22% 是数据访问(load/store)
|
||||
> - 不命中开销均为 40 周期
|
||||
>
|
||||
> **混合 Cache**(32KB):
|
||||
> - 不命中率 1.5%,但 load/store 命中时间 +1 周期
|
||||
> - 平均访存时间 $= 78\% \times (1 + 1.5\% \times 40) + 22\% \times (2 + 1.5\% \times 40) = 1.782$ 周期
|
||||
> **方案一:分离 Cache**(指令 16KB + 数据 16KB = 共 32KB)
|
||||
> - 指令 Cache 不命中率 $mr_I = 1\%$,数据 Cache 不命中率 $mr_D = 5\%$
|
||||
> - 命中时间均为 1 周期(指令和数据各有独立端口,不会冲突)
|
||||
>
|
||||
> **结论**:分离 Cache 更优(1.752 < 1.782)
|
||||
> 逐步计算:
|
||||
> 1. 指令部分平均访存时间 = $1 + 0.01 \times 40 = 1.40$ 周期
|
||||
> 2. 数据部分平均访存时间 = $1 + 0.05 \times 40 = 3.00$ 周期
|
||||
> 3. 加权平均 = $0.78 \times 1.40 + 0.22 \times 3.00 = 1.092 + 0.660 = \mathbf{1.752}$ 周期
|
||||
>
|
||||
> **方案二:混合 Cache**(统一 32KB)
|
||||
> - 整体不命中率 $mr = 1.5\%$(因为容量相同,但指令和数据共享,冲突不命中增加)
|
||||
> - 命中时间:取指仍为 1 周期,但 load/store 需 **+1 周期**(因为指令和数据共用端口,load/store 需要额外仲裁)
|
||||
>
|
||||
> 逐步计算:
|
||||
> 1. 取指平均访存时间 = $1 + 0.015 \times 40 = 1.60$ 周期
|
||||
> 2. 数据平均访存时间 = $2 + 0.015 \times 40 = 2.60$ 周期(命中时间 2 周期)
|
||||
> 3. 加权平均 = $0.78 \times 1.60 + 0.22 \times 2.60 = 1.248 + 0.572 = \mathbf{1.820}$ 周期
|
||||
>
|
||||
> **结论**:分离 Cache 更优(1.752 < 1.820),节省约 $3.7\%$ 的平均访存时间。
|
||||
>
|
||||
> > [!question] 什么时候混合 Cache 反而更好?
|
||||
> > 当数据和指令的访问模式不均匀时——比如某个阶段全是取指(循环),另一阶段全是数据访问——混合 Cache 能让 32KB 容量被充分利用,而分离 Cache 各 16KB 可能不够用。此时混合 Cache 的不命中率可能显著低于分离方案。
|
||||
|
||||
#### 3.3 CPU 时间与 Cache 的关系
|
||||
|
||||
@@ -103,6 +210,35 @@ $$CPU 时间 = IC \times (CPI_{exe} + \frac{\text{访存次数}}{指令} \times
|
||||
|
||||
### 四、17 种 Cache 优化技术
|
||||
|
||||
17 种优化技术围绕 Cache 性能公式中的三个因素展开,分类关系如下:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
ROOT["Cache 性能优化"] --> A["降低不命中率 (8种)"]
|
||||
ROOT --> B["减少不命中开销 (5种)"]
|
||||
ROOT --> C["减少命中时间 (4种)"]
|
||||
|
||||
A --> A1["增大块大小"]
|
||||
A --> A2["增大 Cache 容量"]
|
||||
A --> A3["提高相联度"]
|
||||
A --> A4["伪相联 Cache"]
|
||||
A --> A5["硬件预取"]
|
||||
A --> A6["编译器控制预取"]
|
||||
A --> A7["编译优化"]
|
||||
A --> A8["Victim Cache"]
|
||||
|
||||
B --> B1["非阻塞 Cache"]
|
||||
B --> B2["写合并"]
|
||||
B --> B3["请求字优先"]
|
||||
B --> B4["写缓冲"]
|
||||
B --> B5["早重启"]
|
||||
|
||||
C --> C1["小容量简单 Cache"]
|
||||
C --> C2["虚拟 Cache"]
|
||||
C --> C3["流水化 Cache 访问"]
|
||||
C --> C4["路预测"]
|
||||
```
|
||||
|
||||
| 分类 | 技术 | 基本思想 | 影响 |
|
||||
|:----:|------|----------|------|
|
||||
| **降低不命中率**(8种) | 增大块大小 | 利用空间局部性 | 块过大会增加不命中开销 |
|
||||
@@ -134,6 +270,58 @@ $$CPU 时间 = IC \times (CPI_{exe} + \frac{\text{访存次数}}{指令} \times
|
||||
| **容量不命中**(Capacity) | Cache 容量不足 | 增大 Cache 容量 |
|
||||
| **冲突不命中**(Conflict) | 映射冲突 | 提高相联度、Victim Cache |
|
||||
|
||||
### 六、综合计算题
|
||||
|
||||
> [!example] 综合计算题:Cache 参数计算与性能分析
|
||||
>
|
||||
> **已知条件**:
|
||||
> - 处理器 32 位地址
|
||||
> - Cache 容量 32KB
|
||||
> - 块大小 64B
|
||||
> - 采用 8 路组相联
|
||||
> - LRU 替换策略
|
||||
> - 写回策略
|
||||
> - 命中时间 1 个时钟周期
|
||||
> - 不命中开销 100 个时钟周期
|
||||
> - 不命中率 2%
|
||||
> - 程序中 30% 为访存指令(load/store)
|
||||
>
|
||||
> **问题 1:计算 Tag / Index / Offset 位数**
|
||||
>
|
||||
> - Cache 行数 = $32\text{KB} / 64\text{B} = 512$ 行
|
||||
> - 组数 = $512 / 8 = 64$ 组
|
||||
> - Offset 位数 = $\log_2(64) = 6$ 位
|
||||
> - Index 位数 = $\log_2(64) = 6$ 位
|
||||
> - Tag 位数 = $32 - 6 - 6 = 20$ 位
|
||||
>
|
||||
> | 字段 | Tag | Set Index | Block Offset |
|
||||
> |:----:|:---:|:---------:|:------------:|
|
||||
> | 位数 | 20 | 6 | 6 |
|
||||
> | 位置 | [31:12] | [11:6] | [5:0] |
|
||||
>
|
||||
> **问题 2:计算平均访存时间**
|
||||
>
|
||||
> $$\text{AMAT} = \text{命中时间} + \text{不命中率} \times \text{不命中开销}$$
|
||||
> $$= 1 + 0.02 \times 100 = 1 + 2 = \mathbf{3 \text{ 周期}}$$
|
||||
>
|
||||
> **问题 3:计算对 CPI 的影响**
|
||||
>
|
||||
> 假设理想 CPI(无 Cache 不命中)为 2.0:
|
||||
>
|
||||
> $$\text{实际 CPI} = \text{CPI}_{exe} + \text{访存指令比例} \times \text{不命中率} \times \text{不命中开销}$$
|
||||
> $$= 2.0 + 0.30 \times 0.02 \times 100 = 2.0 + 0.6 = \mathbf{2.6}$$
|
||||
>
|
||||
> Cache 不命中使 CPI 增加了 $0.6$,性能下降了 $30\%$。
|
||||
>
|
||||
> **问题 4:如果将 Cache 容量增大到 64KB(不命中率降为 1%),是否值得?**
|
||||
>
|
||||
> 新的 CPI = $2.0 + 0.30 \times 0.01 \times 100 = 2.0 + 0.3 = 2.3$
|
||||
>
|
||||
> 性能提升 = $(2.6 - 2.3) / 2.6 = 11.5\%$
|
||||
>
|
||||
> > [!question] 如何权衡?
|
||||
> > 64KB Cache 的面积是 32KB 的约 2 倍,但性能仅提升 11.5%。若芯片面积紧张,可考虑用其他优化技术(如提高相联度、硬件预取)来替代简单增大容量——这就是**17 种优化技术的组合运用**。
|
||||
|
||||
## 关联笔记
|
||||
- [[计算机系统结构/复习文档/计算机系统结构基础与定量原理]]
|
||||
- [[计算机系统结构/复习文档/总线与I/O系统]]
|
||||
|
||||
+165
-9
@@ -11,10 +11,10 @@ create time: 2026-06-15 10:00
|
||||
|
||||
## 概述
|
||||
|
||||
本文档讲解总线的基本概念、分离事务总线的工作原理,以及 I/O 系统的性能评价指标。总线是连接处理器、存储器和 I/O 设备的通信通道,其设计直接影响系统整体性能。
|
||||
本文档讲解总线的基本概念、分类与仲裁方式、同步/异步总线的工作机制、分离事务总线的工作原理,以及 I/O 系统的核心组成——DMA 与中断机制。最后讨论 I/O 系统的性能评价与计算方法。总线是连接处理器、存储器和 I/O 设备的通信通道,其设计直接影响系统整体性能。
|
||||
|
||||
> [!tip] 考试重点
|
||||
> 分离事务总线的概念和别称常以选择题出现。I/O 系统性能评价指标需理解各维度的含义。
|
||||
> 分离事务总线的概念和别称常以选择题出现。DMA 三种工作模式的对比、中断处理流程是简答题高频考点。I/O 系统性能计算(总线带宽、CPU 占用率)是综合题常客。
|
||||
|
||||
## 正文
|
||||
|
||||
@@ -36,7 +36,65 @@ create time: 2026-06-15 10:00
|
||||
- **总线宽度**:数据线的位数(如 64 位)
|
||||
- **总线频率**:总线时钟频率(如 800 MHz)
|
||||
|
||||
### 二、分离事务总线
|
||||
三者之间的关系:
|
||||
|
||||
$$\text{总线带宽} = \text{总线宽度} \times \text{总线频率} \times \text{每个时钟传输次数}$$
|
||||
|
||||
> [!question] 思考
|
||||
> 一条 64 位宽、800 MHz 的总线,理论峰值带宽是多少?如果每个时钟周期传输 1 次,答案是 $64 \div 8 \times 800 = 6400\ \text{MB/s}$。若采用 DDR(双倍数据率)技术,带宽翻倍为 12800 MB/s。这就是为什么现代总线普遍采用 DDR 技术。
|
||||
|
||||
#### 1.3 总线仲裁
|
||||
|
||||
多个设备可能同时请求使用总线,**总线仲裁器**(Arbiter)决定谁获得使用权。仲裁方式分为两大类:
|
||||
|
||||
| 仲裁方式 | 仲裁器位置 | 优点 | 缺点 | 典型策略 |
|
||||
|----------|:----------:|------|------|----------|
|
||||
| **集中式仲裁** | 专用硬件仲裁器 | 决策快、确定性强 | 仲裁器是单点瓶颈 | 菊花链、轮询、独立请求 |
|
||||
| **分布式仲裁** | 无集中仲裁器,各设备自行协商 | 可扩展性好 | 延迟不确定 | 自举分布式、冲突检测 |
|
||||
|
||||
**集中式仲裁的三种策略**:
|
||||
|
||||
- **菊花链仲裁**:Grant 信号沿设备链逐级传递,离仲裁器越近优先级越高。简单但不公平,低优先级设备可能饿死。
|
||||
- **轮询仲裁**:仲裁器按固定顺序轮询各设备。公平但效率不高。
|
||||
- **独立请求仲裁**:每个设备有独立的请求/应答线。速度快、灵活,但线数随设备数增加。
|
||||
|
||||
> [!question] 思考
|
||||
> 如果系统中有 16 个 I/O 设备,独立请求仲裁需要多少对请求/应答线?答案是 16 对。设备再多,线数就成了问题——这就是为什么大规模系统倾向于使用分布式仲裁或层级式仲裁。
|
||||
|
||||
### 二、同步总线与异步总线
|
||||
|
||||
总线通信的同步方式决定了设备间如何协调时序。
|
||||
|
||||
#### 2.1 同步总线
|
||||
|
||||
所有操作由**统一的时钟信号**驱动。发送方和接收方在时钟边沿进行数据采样。
|
||||
|
||||
- 优点:控制简单、速度快
|
||||
- 缺点:所有设备必须以同一时钟频率工作,灵活性差;总线长度受时钟偏移(clock skew)限制
|
||||
|
||||
#### 2.2 异步总线
|
||||
|
||||
没有统一时钟,通过**握手信号**(Handshake)协调通信。典型的四周期握手协议如下:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant S as "发送方"
|
||||
participant R as "接收方"
|
||||
|
||||
S->>R: "1. 数据就绪 (Data Valid)"
|
||||
R->>S: "2. 数据接收 (Data Ack)"
|
||||
S->>R: "3. 撤销数据就绪"
|
||||
R->>S: "4. 撤销数据接收"
|
||||
Note over S, R: "一个完整的四周期握手完成"
|
||||
```
|
||||
|
||||
- 优点:允许不同速度的设备通信,灵活性高
|
||||
- 缺点:握手开销增加了延迟,速度比同步总线慢
|
||||
|
||||
> [!note] 半同步总线
|
||||
> 实际系统常采用**半同步总线**:以时钟为基本定时参考,但引入 `Wait` 信号允许慢速设备插入等待周期。兼顾了同步的效率和异步的灵活性。
|
||||
|
||||
### 三、分离事务总线
|
||||
|
||||
**核心思想**:将一个总线事务分成**请求**和**响应**两个阶段,在请求和响应之间的空闲时间内,总线可以供给其他 I/O 设备使用。
|
||||
|
||||
@@ -48,7 +106,7 @@ sequenceDiagram
|
||||
|
||||
C->>B: 请求阶段(发送地址+命令)
|
||||
B->>M: 内存准备数据
|
||||
Note over B: 总线空闲,可服务其他请求
|
||||
Note over B: "总线空闲, 可服务其他请求"
|
||||
M->>B: 响应阶段(返回数据)
|
||||
B->>C: 数据到达
|
||||
```
|
||||
@@ -65,9 +123,9 @@ sequenceDiagram
|
||||
> [!note] 分离事务总线的优势
|
||||
> 传统总线在一个事务完成前一直被占用,分离事务总线在等待内存响应时释放总线,允许多个设备并发使用,显著提高总线利用率。
|
||||
|
||||
### 三、I/O 系统性能
|
||||
### 四、I/O 系统性能
|
||||
|
||||
#### 3.1 性能评价维度
|
||||
#### 4.1 性能评价维度
|
||||
|
||||
| 维度 | 含义 | 衡量指标 |
|
||||
|------|------|----------|
|
||||
@@ -79,7 +137,7 @@ sequenceDiagram
|
||||
> [!question] I/O 系统性能为什么重要?
|
||||
> 随着处理器速度远超 I/O 设备速度,I/O 瓶颈日益突出。一个 I/O 操作可能耗时数毫秒,而 CPU 一个时钟周期仅数纳秒,巨大的速度差使得 I/O 系统可能成为整个系统的瓶颈。
|
||||
|
||||
#### 3.2 I/O 系统的瓶颈问题
|
||||
#### 4.2 I/O 系统的瓶颈问题
|
||||
|
||||
```
|
||||
CPU 速度: ~GHz (纳秒级)
|
||||
@@ -93,7 +151,45 @@ CPU 速度: ~GHz (纳秒级)
|
||||
- I/O 和 CPU 的性能不匹配时,I/O 系统成为瓶颈
|
||||
- 需要通过缓存、缓冲、异步 I/O 等技术缓解
|
||||
|
||||
### 四、DMA 与中断
|
||||
#### 4.3 I/O 性能计算
|
||||
|
||||
> [!example] 例题:总线带宽与 I/O 吞吐量
|
||||
> 某计算机系统参数如下:
|
||||
>
|
||||
> - 总线宽度:64 位
|
||||
> - 总线频率:200 MHz
|
||||
> - 每个总线周期传输 1 次数据
|
||||
> - 系统通过 DMA 将磁盘数据传入内存
|
||||
> - DMA 采用块传输模式,每个总线事务的开销为 2 个周期(地址+命令 1 周期,数据传输 1 周期)
|
||||
>
|
||||
> **问题 1**:总线的理论峰值带宽是多少?
|
||||
>
|
||||
> **解**:
|
||||
>
|
||||
> $\text{理论带宽} = 64\text{bit} \times 200\text{MHz} = 1600\text{MB/s}$
|
||||
>
|
||||
> **问题 2**:考虑事务开销后,实际有效带宽是多少?
|
||||
>
|
||||
> **解**:
|
||||
>
|
||||
> 每传输 64 bit(8 B)数据需要 2 个周期(1 个开销 + 1 个数据)
|
||||
>
|
||||
> $\text{有效带宽} = \frac{8\text{B}}{2 \times 5\text{ns}} = 800\text{MB/s}$
|
||||
>
|
||||
> **问题 3**:如果有 4 个磁盘控制器同时以 DMA 方式向内存写入数据,每个控制器持续传输速率为 150 MB/s,总线能否支持?
|
||||
>
|
||||
> **解**:
|
||||
>
|
||||
> 总需求带宽:$4 \times 150 = 600\text{MB/s}$
|
||||
>
|
||||
> 有效带宽 800 MB/s > 600 MB/s,可以支持。但总线利用率已达 $600/800 = 75\%$,余量不多。如果再增加设备或提高单设备速率,总线将成为瓶颈。
|
||||
|
||||
> [!question] 思考
|
||||
> 为什么分离事务总线能提高 I/O 系统的有效带宽?因为它在等待内存响应期间释放总线给其他设备使用,减少了总线空闲时间。在上例中,如果采用传统总线,每个 DMA 事务期间总线被独占(即使设备在准备数据),有效带宽会进一步下降。
|
||||
|
||||
### 五、DMA 与中断
|
||||
|
||||
#### 5.1 三种 I/O 控制方式对比
|
||||
|
||||
| 方式 | 原理 | CPU 参与度 | 适用场景 |
|
||||
|------|------|:----------:|----------|
|
||||
@@ -101,12 +197,72 @@ CPU 速度: ~GHz (纳秒级)
|
||||
| 中断 | I/O 完成后通知 CPU | 中 | 低速设备 |
|
||||
| **DMA** | 直接内存访问,不经过 CPU | 低 | 高速设备 |
|
||||
|
||||
DMA 的工作流程:
|
||||
#### 5.2 DMA 工作流程
|
||||
|
||||
1. CPU 设置 DMA 传输参数(源地址、目的地址、传输长度)
|
||||
2. DMA 控制器接管总线,直接在设备和内存间传输数据
|
||||
3. 传输完成后,DMA 控制器向 CPU 发中断通知
|
||||
|
||||
#### 5.3 DMA 的三种工作模式
|
||||
|
||||
DMA 控制器在传输过程中根据总线使用权的不同,分为三种工作模式:
|
||||
|
||||
| 模式 | 总线使用方式 | CPU 影响 | 传输效率 | 适用场景 |
|
||||
|------|------------|:--------:|:--------:|----------|
|
||||
| **单字传输**(Cycle Stealing) | 每传一个字就释放总线给 CPU | 每个字都要"偷"一个总线周期,CPU 频繁被打断 | 低 | CPU 对延迟敏感的场景 |
|
||||
| **块传输**(Block Transfer) | 一次占用总线传完整个数据块 | CPU 长时间无法使用总线 | 高 | 大块数据连续传输 |
|
||||
| **请求传输**(Demand Transfer) | DMA 检查 DREQ 信号,设备未就绪则释放总线 | 仅在设备有数据时才占用总线 | 中等 | 设备速度不确定的场景 |
|
||||
|
||||
> [!question] 思考
|
||||
> 假设 CPU 每秒执行 1 亿条指令,DMA 以单字模式从磁盘读取数据,总线宽度 32 位,总线周期 100ns。每"偷"一个周期 CPU 损失一条指令的时间。若传输 1 MB 数据,CPU 会损失多少执行时间?答案:$1\text{MB} \div 4\text{B} = 250000$ 个周期,损失 $250000 \times 100\text{ns} = 25\text{ms}$,占 1 秒的 2.5%。这就是为什么高速传输通常选择块传输模式。
|
||||
|
||||
#### 5.4 中断处理的完整流程
|
||||
|
||||
当 I/O 设备完成操作后,通过中断通知 CPU。CPU 响应中断的完整过程如下:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["中断请求"] --> B{"CPU 响应?"}
|
||||
B -- "否" --> A
|
||||
B -- "是" --> C["关中断"]
|
||||
C --> D["保护现场: 保存 PC, PSW 等"]
|
||||
D --> E["识别中断源: 确定哪个设备中断"]
|
||||
E --> F["跳转中断服务程序"]
|
||||
F --> G["执行中断服务: 处理 I/O 数据"]
|
||||
G --> H["恢复现场: 恢复 PC, PSW 等"]
|
||||
H --> I["开中断"]
|
||||
I --> J["返回断点继续执行"]
|
||||
```
|
||||
|
||||
> [!important] 关键步骤说明
|
||||
> - **保护现场**:必须保存程序计数器(PC)和程序状态字(PSW),确保中断返回后能正确继续执行。
|
||||
> - **中断源识别**:多个设备同时中断时,需要确定优先级。硬件向量法比软件轮询法快得多。
|
||||
> - **嵌套中断**:中断服务期间是否允许新的更高优先级中断嵌入?这取决于是否在服务程序中开中断。
|
||||
|
||||
#### 5.5 中断 vs DMA 的 CPU 占用率计算
|
||||
|
||||
> [!example] 例题:I/O 系统 CPU 占用率
|
||||
> 一个系统中,CPU 时钟频率 500 MHz,磁盘控制器以 DMA 方式传输数据。
|
||||
>
|
||||
> - DMA 采用块传输模式,每次传输 4 KB 数据块
|
||||
> - 传输前 CPU 需要 1000 个时钟周期设置 DMA 控制器
|
||||
> - 传输完成后 DMA 中断 CPU,中断处理需要 500 个时钟周期
|
||||
> - 磁盘持续数据传输速率为 40 MB/s
|
||||
>
|
||||
> **问题**:CPU 用于该磁盘 I/O 的时间比例是多少?
|
||||
>
|
||||
> **解**:
|
||||
>
|
||||
> 每个 4 KB 块需要 CPU 参与的周期数:$1000 + 500 = 1500$ 个周期
|
||||
>
|
||||
> 每秒传输的块数:$40\text{MB/s} \div 4\text{KB} = 10000$ 块/秒
|
||||
>
|
||||
> 每秒 CPU 花在 I/O 上的周期数:$10000 \times 1500 = 1.5 \times 10^7$ 周期/秒
|
||||
>
|
||||
> CPU 占用率:$1.5 \times 10^7 \div 5 \times 10^8 = 3\%$
|
||||
>
|
||||
> **结论**:DMA 的 CPU 占用率仅 3%。如果采用中断方式逐字传输,每次传输 1 个字(4B)都需要一次中断,CPU 占用率将大幅飙升。
|
||||
|
||||
## 关联笔记
|
||||
- [[计算机系统结构/复习文档/计算机系统结构基础与定量原理]]
|
||||
- [[计算机系统结构/复习文档/存储系统与Cache]]
|
||||
|
||||
@@ -50,6 +50,18 @@ create time: 2026-06-15 10:00
|
||||
2. 使用频率低的指令分配长操作码
|
||||
3. 短操作码不能是长操作码的前缀
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["Determine Instruction Word Length"] --> B["Allocate Address Fields"]
|
||||
B --> C["Calculate Remaining Bits for Opcode"]
|
||||
C --> D["Assign Short Opcodes to Frequent Instructions"]
|
||||
D --> E["Use Remaining Encoding Space as Extension Flag"]
|
||||
E --> F["Allocate Longer Opcodes for Less Frequent Instructions"]
|
||||
F --> G{"All Instruction Types Covered?"}
|
||||
G -- No --> E
|
||||
G -- Yes --> H["Design Complete"]
|
||||
```
|
||||
|
||||
> [!example] 例:12 位指令字长,3 位地址字段
|
||||
>
|
||||
> | 类型 | 操作码 | 地址数 | 可用编码空间 |
|
||||
@@ -58,6 +70,51 @@ create time: 2026-06-15 10:00
|
||||
> | 二地址 | 6 位 | 2 | 余下 4 个 × $2^3 = 32$(用 8 个) |
|
||||
> | 单地址 | 9 位 | 1 | 余下编码 × $2^3 = 190$ 条 |
|
||||
|
||||
> [!example] 综合例题:扩展操作码指令格式设计
|
||||
>
|
||||
> **题目**:某计算机指令字长 16 位,每个地址字段 4 位。要求设计扩展操作码,使得:
|
||||
> - 三地址指令 15 条
|
||||
> - 二地址指令 15 条
|
||||
> - 单地址指令 15 条
|
||||
> - 零地址指令尽可能多
|
||||
>
|
||||
> 求各类指令的编码方案及零地址指令的最大数量。
|
||||
>
|
||||
> **解题步骤**:
|
||||
>
|
||||
> **第一步**:确定各字段位数
|
||||
>
|
||||
> 指令字长 16 位,地址字段 4 位。三地址指令需 $4 \times 3 = 12$ 位用于地址,剩余 $16 - 12 = 4$ 位用于操作码。
|
||||
>
|
||||
> **第二步**:计算三地址指令空间
|
||||
>
|
||||
> 4 位操作码最多表示 $2^4 = 16$ 种编码,实际需要 15 条,剩余 1 个编码作为扩展标志。
|
||||
>
|
||||
> **第三步**:计算二地址指令空间
|
||||
>
|
||||
> 二地址指令:操作码 = 4 位(前缀)+ 4 位(第一地址字段扩展)= 8 位,地址占 $4 \times 2 = 8$ 位。由扩展标志 $1 \times 2^4 = 16$ 种编码,实际用 15 条,剩余 1 个继续扩展。
|
||||
>
|
||||
> **第四步**:计算单地址指令空间
|
||||
>
|
||||
> 单地址指令:操作码 = 8 位 + 4 位 = 12 位,地址占 4 位。由扩展标志 $1 \times 2^4 = 16$ 种编码,实际用 15 条,剩余 1 个继续扩展。
|
||||
>
|
||||
> **第五步**:计算零地址指令空间
|
||||
>
|
||||
> 零地址指令:操作码占满 16 位。由扩展标志 $1 \times 2^4 = 16$ 条。
|
||||
>
|
||||
> **结果汇总**:
|
||||
>
|
||||
> | 类型 | 操作码位数 | 地址字段位数 | 指令数量 |
|
||||
> |:----:|:---------:|:----------:|:-------:|
|
||||
> | 三地址 | 4 位 | 12 位 | 15 条 |
|
||||
> | 二地址 | 8 位 | 8 位 | 15 条 |
|
||||
> | 单地址 | 12 位 | 4 位 | 15 条 |
|
||||
> | 零地址 | 16 位 | 0 位 | 16 条 |
|
||||
>
|
||||
> 共计 $15 + 15 + 15 + 16 = 61$ 条指令。
|
||||
>
|
||||
> **关键技巧**:每层保留的扩展标志数量决定了下一层的编码空间。如果某层需要 $k$ 条指令,操作码有 $n$ 位,则保留 $2^n - k$ 个标志位用于向下扩展。
|
||||
|
||||
### 三、RISC vs CISC
|
||||
|
||||
| 特性 | RISC | CISC |
|
||||
@@ -71,6 +128,22 @@ create time: 2026-06-15 10:00
|
||||
| 寄存器 | 多(32+ 通用寄存器) | 少 |
|
||||
| 编译器 | 依赖编译器优化 | 硬件承担更多 |
|
||||
|
||||
**历史背景与设计理念**:
|
||||
|
||||
20 世纪 70 年代末,IBM 的 John Cocke 等人通过研究发现,实际程序中 80% 的执行时间只用到了 20% 的指令——这就是著名的 **80/20 法则**。基于此观察,精简指令集(RISC)的设计理念应运而生:
|
||||
|
||||
- **CISC 路线**(以 Intel x86 为代表):通过增加指令数量和复杂度来缩小"语义鸿沟",一条指令完成更多工作,减少程序体积和访存次数。代价是硬件复杂度高、设计周期长、功耗大。
|
||||
- **RISC 路线**(以 ARM、MIPS 为代表):只保留最常用的简单指令,通过编译器组合来实现复杂功能。硬件简单、时钟频率高、易于流水线化。
|
||||
|
||||
> [!note] 历史上的关键节点
|
||||
> - 1964 年:IBM System/360 奠定 CISC 基础,引入微程序控制
|
||||
> - 1980 年:Berkeley RISC-I 和 Stanford MIPS 项目验证了 RISC 可行性
|
||||
> - 1985 年:ARM1 诞生,RISC 进入商业领域
|
||||
> - 如今:x86 处理器内部将 CISC 指令翻译为类 RISC 微操作执行,两种路线殊途同归
|
||||
|
||||
> [!question] RISC 和 CISC 哪个更好?
|
||||
> 这是一个没有标准答案的问题。CISC 减少了指令条数但增加了硬件复杂度;RISC 简化了硬件但增加了程序体积。现代处理器实际上融合了两者优点——x86 内核已经是"RISC 核心 + CISC 前端"的混合架构。
|
||||
|
||||
> [!warning] RISC 的常见误解
|
||||
> - RISC 不是"指令功能简单",而是"指令数量少、格式规整"
|
||||
> - RISC 的单周期是指理想情况,Cache 不命中等仍会导致多周期
|
||||
@@ -90,6 +163,58 @@ create time: 2026-06-15 10:00
|
||||
| 基址寻址 | EA = R + A | 数组基址 |
|
||||
| 变址寻址 | EA = A + R | 数组下标 |
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A["Instruction Decoded"] --> B{"Addressing Mode"}
|
||||
B -- Immediate --> C["Operand = Address Field A"]
|
||||
B -- Register --> D["EA = Register R"]
|
||||
B -- Direct --> E["EA = Address Field A"]
|
||||
B -- Indirect --> F["Fetch Content at A"]
|
||||
F --> G["EA = Content"]
|
||||
B -- Base --> H["EA = Base Register R + Offset A"]
|
||||
B -- Index --> I["EA = Index Register R + Base Address A"]
|
||||
```
|
||||
|
||||
> [!question] 基址寻址和变址寻址看起来公式一样(都是 R + A),有什么区别?
|
||||
> 区别在于**使用场景和硬件支持**。基址寻址中,R 由操作系统设置(程序不能改),A 是指令中的偏移量,用于实现**程序重定位**和**数组基址**访问。变址寻址中,R 由用户程序修改(如循环中 R++),A 是固定基地址,用于实现**数组下标遍历**。在 RISC 架构中,两者通常不做区分,统一用寄存器+偏移量的寻址方式。
|
||||
|
||||
> [!example] 综合题:指令格式设计
|
||||
>
|
||||
> **题目**:某计算机字长 32 位,指令字长 16 位。要求:
|
||||
> - 支持 4 种操作:加、减、乘、除(操作码 2 位即可)
|
||||
> - 需要 64 个通用寄存器
|
||||
> - 支持立即数寻址和寄存器寻址两种模式
|
||||
> - 立即数范围:$-128 \sim 127$
|
||||
>
|
||||
> 设计最优的指令编码格式。
|
||||
>
|
||||
> **解题步骤**:
|
||||
>
|
||||
> **第一步**:确定各字段所需位数
|
||||
>
|
||||
> | 字段 | 位数 | 理由 |
|
||||
> |:----:|:----:|------|
|
||||
> | 操作码 | 2 位 | 4 种操作,$2^2 = 4$ |
|
||||
> | 寄存器编号 | 6 位 | 64 个寄存器,$\log_2 64 = 6$ |
|
||||
> | 寻址模式 | 1 位 | 2 种模式 |
|
||||
>
|
||||
> **第二步**:设计寄存器寻址格式
|
||||
>
|
||||
> 两个操作数都是寄存器:操作码 + 模式位 + Rs + Rd = $2 + 1 + 6 + 6 = 15$ 位,剩余 1 位可用于功能扩展或保留。
|
||||
>
|
||||
> **第三步**:设计立即数寻址格式
|
||||
>
|
||||
> 操作码 + 模式位 + Rd + 立即数 = $2 + 1 + 6 + 7 = 16$ 位,恰好填满。7 位立即数可表示 $-128 \sim 127$,满足要求。
|
||||
>
|
||||
> **结果**:
|
||||
>
|
||||
> ```
|
||||
> 寄存器寻址:[操作码 2 位][模式 1 位][Rs 6 位][Rd 6 位][保留 1 位]
|
||||
> 立即数寻址:[操作码 2 位][模式 1 位][Rd 6 位][立即数 7 位]
|
||||
> ```
|
||||
>
|
||||
> **启示**:指令格式设计是一个**位数分配的优化问题**——在固定的指令字长约束下,权衡操作码空间、寄存器数量、寻址模式和立即数范围。
|
||||
|
||||
## 关联笔记
|
||||
- [[计算机系统结构/复习文档/计算机系统结构基础与定量原理]]
|
||||
- [[计算机系统结构/复习文档/流水线技术]]
|
||||
|
||||
+174
-14
@@ -62,6 +62,30 @@ graph LR
|
||||
> [!question] 定向传送(旁路)为什么不能完全消除数据冲突?
|
||||
> Load-use 冲突:从内存 Load 的数据在 EX 段结束时才可用,但下一条指令可能需要在 EX 段开始时就使用它,此时必须插入一个气泡。
|
||||
|
||||
**Load-use 冲突 vs Forwarding 效果对比**:
|
||||
|
||||
假设指令序列为 `LW R1, 0(R2)` → `ADD R3, R1, R4`,Load 指令的 R1 在 MEM 段末才从存储器读出,而 ADD 指令在 EX 段开头就需要 R1 的值。
|
||||
|
||||
| 时钟周期 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
|:--------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|
||||
| **无 Forwarding,无 Stall** | | | | | | | | |
|
||||
| `LW R1` | IF | ID | EX | MEM | WB | | | |
|
||||
| `ADD R3,R1,R4` | | IF | ID | **EX** | MEM | WB | | |
|
||||
| **有 Stall,无 Forwarding** | | | | | | | | |
|
||||
| `LW R1` | IF | ID | EX | MEM | WB | | | |
|
||||
| `ADD R3,R1,R4` | | IF | ID | **Stall** | EX | MEM | WB | |
|
||||
| **有 Forwarding(Load-use 需 1 拍 Stall)** | | | | | | | | |
|
||||
| `LW R1` | IF | ID | EX | MEM | WB | | | |
|
||||
| `ADD R3,R1,R4` | | IF | ID | **Stall** | EX | MEM | WB | |
|
||||
| **理想 Forwarding(非 Load 指令)** | | | | | | | | |
|
||||
| `ADD R1,...` | IF | ID | EX | MEM | WB | | | |
|
||||
| `ADD R3,R1,R4` | | IF | ID | EX | MEM | WB | | |
|
||||
|
||||
> [!important] 关键区别
|
||||
> - **EX→EX 前推**(非 Load 指令):结果在 EX 段末产生,下一条指令 EX 段初可用,**无需 Stall**
|
||||
> - **MEM→EX 前推**(Load-use):数据在 MEM 段末才可用,但下一条指令 EX 段初就需要,**必须插入 1 拍 Stall**
|
||||
> - 这就是为什么 Load-use 冲突无法被完全消除的根本原因——**存在一拍的物理时间差**
|
||||
|
||||
#### 2.3 控制冲突(Control Hazard)
|
||||
|
||||
分支指令的执行结果决定后续取指方向,但在分支确定前已经预取了后续指令。
|
||||
@@ -74,6 +98,8 @@ graph LR
|
||||
|
||||
### 三、流水线调度(非线性流水线)
|
||||
|
||||
非线性流水线中,各段的使用存在重叠冲突,不能简单地每拍送入新任务。需要通过**预约表分析**确定安全的调度间隔。
|
||||
|
||||
#### 3.1 预约表
|
||||
|
||||
记录一个任务在各时钟周期对各段的占用情况,是调度分析的起点。
|
||||
@@ -97,14 +123,6 @@ $$C_{new} = SHR^{(j)}(C) \lor C_0$$
|
||||
|
||||
其中 $SHR^{(j)}$ 表示右移 $j$ 位,$\lor$ 表示按位或。
|
||||
|
||||
> [!example] 调度示例
|
||||
> 禁止表 $F = \{1, 3, 4, 6\}$,则 $C_0 = 101101$
|
||||
>
|
||||
> - $j=2$:$SHR^{(2)}(101101) \lor 101101 = 001011 \lor 101101 = 101111 = C_1$
|
||||
> - $j=5$:$SHR^{(5)}(101101) \lor 101101 = 000001 \lor 101101 = 101101 = C_0$
|
||||
>
|
||||
> 在 $C_1$ 状态:$j=2$ 得 $C_1$,$j=5$ 得 $C_0$
|
||||
|
||||
#### 3.5 最优调度策略
|
||||
|
||||
在状态转移图中找出所有**闭合回路**,计算每个回路的平均延迟:
|
||||
@@ -113,13 +131,79 @@ $$\text{平均延迟} = \frac{\text{回路中各间隔之和}}{\text{回路长
|
||||
|
||||
平均延迟最小的回路即为最优调度策略。
|
||||
|
||||
| 调度策略 | 平均延迟 |
|
||||
|:--------:|:--------:|
|
||||
| (5) | 5 |
|
||||
| (2, 5) | 3.5 |
|
||||
| (2, 7) | 4.5 |
|
||||
> [!example] 完整例题:从预约表到最优调度
|
||||
>
|
||||
> **已知**某非线性流水线预约表如下(3 段:S1, S2, S3,7 个时钟周期):
|
||||
>
|
||||
> | 段 \\ 时刻 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
> |:----------:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|
||||
> | S1 | x | | | | x | | |
|
||||
> | S2 | | x | | x | | | |
|
||||
> | S3 | | | x | | | | x |
|
||||
>
|
||||
> **Step 1:提取禁止表 F**
|
||||
>
|
||||
> - S1 在时刻 1 和 5 被占用,间隔 = 5 - 1 = **4**
|
||||
> - S2 在时刻 2 和 4 被占用,间隔 = 4 - 2 = **2**
|
||||
> - S3 在时刻 3 和 7 被占用,间隔 = 7 - 3 = **4**
|
||||
>
|
||||
> 因此禁止表 $F = \{2, 4\}$(去掉重复的 4)
|
||||
>
|
||||
> **Step 2:构建初始冲突向量 $C_0$**
|
||||
>
|
||||
> 最大禁止间隔为 4,冲突向量共 4 位(第 1~4 位),第 $i$ 位为 1 表示间隔 $i$ 禁止:
|
||||
>
|
||||
> $$C_0 = 1010$$
|
||||
>
|
||||
> 其中第 2 位和第 4 位为 1(对应禁止间隔 2 和 4),第 1 位和第 3 位为 0(对应允许间隔 1 和 3)。
|
||||
>
|
||||
> **Step 3:计算各状态转移**
|
||||
>
|
||||
> 初始状态 $C_0 = 1010$,允许间隔为 $j \in \{1, 3\}$:
|
||||
>
|
||||
> - $j=1$:$SHR^{(1)}(1010) \lor 1010 = 0101 \lor 1010 = 1111 = C_1$
|
||||
> - $j=3$:$SHR^{(3)}(1010) \lor 1010 = 0001 \lor 1010 = 1011 = C_2$
|
||||
>
|
||||
> 状态 $C_1 = 1111$,所有位为 1,不允许任何间隔,为**终态**。
|
||||
>
|
||||
> 状态 $C_2 = 1011$,第 2 位为 0,允许间隔 $j=2$:
|
||||
>
|
||||
> - $j=2$:$SHR^{(2)}(1011) \lor 1010 = 0010 \lor 1010 = 1010 = C_0$
|
||||
>
|
||||
> **Step 4:画状态转移图**
|
||||
>
|
||||
> ```mermaid
|
||||
> graph LR
|
||||
> C0["C0 = 1010"] -->|"j = 1"| C1["C1 = 1111"]
|
||||
> C0 -->|"j = 3"| C2["C2 = 1011"]
|
||||
> C2 -->|"j = 2"| C0
|
||||
> ```
|
||||
>
|
||||
> **Step 5:找最优调度策略**
|
||||
>
|
||||
> 从 $C_0$ 出发,找到所有闭合回路:
|
||||
>
|
||||
> | 回路 | 间隔序列 | 平均延迟 |
|
||||
> |:----:|:--------:|:--------:|
|
||||
> | $C_0 \xrightarrow{j=3} C_2 \xrightarrow{j=2} C_0$ | (3, 2) | $\frac{3+2}{2} = 2.5$ 拍 |
|
||||
>
|
||||
> 这是唯一可循环的回路,**最优调度策略为 (3, 2)**,平均延迟 **2.5 拍**。
|
||||
>
|
||||
> > [!tip] 验证
|
||||
> > 按 (3, 2, 3, 2, ...) 调度,任务进入时刻为 0, 3, 5, 8, 10, 13, ...
|
||||
> > 每个任务 7 拍完成,5 个任务在时刻 0~17 完成,吞吐率 = $5/18 \approx 0.278$(远优于串行的 $1/7 \approx 0.143$)
|
||||
|
||||
最优策略为 **(2, 5)**,平均延迟 3.5 拍。
|
||||
**状态转移图示例**(与上面例题对应的图示化表达):
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
C0["C0 = 1010"] -->|"j = 1"| C1["C1 = 1111 (终态)"]
|
||||
C0 -->|"j = 3"| C2["C2 = 1011"]
|
||||
C2 -->|"j = 2"| C0
|
||||
```
|
||||
|
||||
> [!question] 为什么 C1 = 1111 是"死胡同"?
|
||||
> 当所有位都为 1 时,没有任何间隔是允许的——此时流水线已完全阻塞,新任务无法进入。因此在实际调度中应**避免进入此类状态**,本题的最优回路 (3,2) 恰好避开了 C1。
|
||||
|
||||
### 四、时空图分析
|
||||
|
||||
@@ -132,6 +216,82 @@ $$\text{平均延迟} = \frac{\text{回路中各间隔之和}}{\text{回路长
|
||||
3. 注意数据相关的约束(无定向传送时需插入气泡)
|
||||
4. 计算总完成时间和吞吐率
|
||||
|
||||
> [!example] 数值化示例:4 段流水线性能分析
|
||||
>
|
||||
> **已知**:4 段流水线(S1, S2, S3, S4),各段延迟分别为 2ns, 4ns, 3ns, 2ns。时钟周期取最长段延迟 = 4ns。连续执行 5 个任务。
|
||||
>
|
||||
> **情况 A:线性流水线,无冲突**
|
||||
>
|
||||
> | 任务 \\ 段 | S1(2ns) | S2(4ns) | S3(3ns) | S4(2ns) | 完成时刻 |
|
||||
> |:----------:|:-------:|:-------:|:-------:|:-------:|:--------:|
|
||||
> | T1 | 0-4 | 4-8 | 8-12 | 12-16 | 16 |
|
||||
> | T2 | 4-8 | 8-12 | 12-16 | 16-20 | 20 |
|
||||
> | T3 | 8-12 | 12-16 | 16-20 | 20-24 | 24 |
|
||||
> | T4 | 12-16 | 16-20 | 20-24 | 24-28 | 28 |
|
||||
> | T5 | 16-20 | 20-24 | 24-28 | 28-32 | 32 |
|
||||
>
|
||||
> - 总时间 $T_k = (4-1) \times 4 + (2+4+3+2) = 12 + 11 = 23$ ns(但按 4ns 时钟周期计算 = 32ns)
|
||||
> - 串行时间 $T_{seq} = 5 \times (2+4+3+2) = 55$ ns
|
||||
> - 吞吐率 $TP = 5/32 = 0.156$ 任务/ns
|
||||
> - 加速比 $S = 55/32 = 1.72$
|
||||
> - 效率 $E = 1.72/4 = 43\%$
|
||||
>
|
||||
> > [!question] 为什么效率只有 43%?
|
||||
> > 因为各段延迟不均衡(S2 占 4ns,S1 和 S4 只占 2ns),S1 和 S4 的大部分时间处于空闲状态。这就是**段间不均衡**带来的效率损失——改善方法是**细分较长段**或**合并较短段**。
|
||||
|
||||
> [!example] 综合计算题:含数据冲突的流水线性能
|
||||
>
|
||||
> **已知**:5 段流水线(IF/ID/EX/MEM/WB),每段 1 时钟周期。执行以下指令序列:
|
||||
>
|
||||
> ```
|
||||
> I1: LW R1, 0(R2) ; Load R1 from memory
|
||||
> I2: ADD R3, R1, R4 ; R3 = R1 + R4 (RAW on R1, Load-use)
|
||||
> I3: SUB R5, R3, R6 ; R5 = R3 - R6 (RAW on R3)
|
||||
> I4: SW R5, 0(R7) ; Store R5 to memory (RAW on R5)
|
||||
> ```
|
||||
>
|
||||
> **问题**:(a) 无 Forwarding 时需要多少 Stall?(b) 有 Forwarding 时需要多少 Stall?(c) 分别计算加速比和效率。
|
||||
>
|
||||
> **(a) 无 Forwarding**
|
||||
>
|
||||
> | 时钟 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|
||||
> |:----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:--:|:--:|:--:|
|
||||
> | I1 LW | IF | ID | EX | MEM | WB | | | | | | | |
|
||||
> | I2 ADD | | IF | ID | **S** | **S** | EX | MEM | WB | | | | |
|
||||
> | I3 SUB | | | IF | **S** | **S** | ID | **S** | **S** | EX | MEM | WB | |
|
||||
> | I4 SW | | | | | | IF | **S** | **S** | ID | **S** | **S** | EX... |
|
||||
>
|
||||
> 解释:I2 等 I1 在 WB 后才能读 R1(需等 2 拍);I3 等 I2 在 WB 后才能读 R3;I4 等 I3 在 WB 后才能读 R5。
|
||||
>
|
||||
> 无 Forwarding 总共需要 **8 个 Stall 拍**。
|
||||
>
|
||||
> **(b) 有 Forwarding(Load-use 需 1 拍 Stall)**
|
||||
>
|
||||
> | 时钟 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
> |:----:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|
||||
> | I1 LW | IF | ID | EX | MEM | WB | | | |
|
||||
> | I2 ADD | | IF | ID | **S** | EX | MEM | WB | |
|
||||
> | I3 SUB | | | IF | ID | EX | MEM | WB | |
|
||||
> | I4 SW | | | | IF | ID | EX | MEM | WB |
|
||||
>
|
||||
> 解释:
|
||||
> - I2 的 R1 依赖 I1(Load-use):数据在 MEM 末可用,I2 需在 EX 初使用,插入 **1 拍 Stall**
|
||||
> - I3 的 R3 依赖 I2(非 Load,EX→EX 前推):**无需 Stall**
|
||||
> - I4 的 R5 依赖 I3(非 Load,EX→EX 前推):**无需 Stall**
|
||||
>
|
||||
> 有 Forwarding 仅需 **1 个 Stall 拍**。
|
||||
>
|
||||
> **(c) 性能对比**
|
||||
>
|
||||
> | 指标 | 无 Forwarding | 有 Forwarding |
|
||||
> |:----:|:------------:|:-------------:|
|
||||
> | 总拍数 | 12 拍 | 8 拍 |
|
||||
> | 串行时间 | $4 \times 5 = 20$ 拍 | 20 拍 |
|
||||
> | 加速比 | $20/12 \approx 1.67$ | $20/8 = 2.5$ |
|
||||
> | 效率 | $1.67/5 = 33.3\%$ | $2.5/5 = 50\%$ |
|
||||
>
|
||||
> Forwarding 将加速比提升了 **50%**(从 1.67 到 2.5),这就是为什么现代处理器都实现了 Forwarding 旁路网络。
|
||||
|
||||
## 关联笔记
|
||||
- [[计算机系统结构/复习文档/计算机系统结构基础与定量原理]]
|
||||
- [[计算机系统结构/复习文档/存储系统与Cache]]
|
||||
|
||||
@@ -73,6 +73,36 @@ $$S = \frac{1}{(1-f) + \frac{f}{n}}$$
|
||||
> [!question] 某功能占系统时间 20%,提升 15 倍,加速比是多少?
|
||||
> $S = \frac{1}{0.8 + 0.2/15} = \frac{1}{0.8133} \approx 1.23$。即使将该功能提升到无限快,加速比上限也只有 $1/0.8 = 1.25$。
|
||||
|
||||
> [!example] 综合例题:多部件同时改进
|
||||
>
|
||||
> **题目**:某系统由三个部件组成,执行时间占比及改进方案如下:
|
||||
>
|
||||
> | 部件 | 原始时间占比 | 改进后加速倍数 |
|
||||
> |:----:|:----------:|:-------------:|
|
||||
> | A | 40% | 3 倍 |
|
||||
> | B | 35% | 2 倍 |
|
||||
> | C | 25% | 不改进 |
|
||||
>
|
||||
> 求系统总加速比。
|
||||
>
|
||||
> **解题步骤**:
|
||||
>
|
||||
> **第一步**:确定各部件改进后的时间比例
|
||||
>
|
||||
> 改进后,各部件在总时间中的占比变为:
|
||||
>
|
||||
> $$T_{new} = (1-f_A-f_B-f_C) + \frac{f_A}{n_A} + \frac{f_B}{n_B} + \frac{f_C}{n_C}$$
|
||||
>
|
||||
> **第二步**:代入数值
|
||||
>
|
||||
> $$T_{new} = 0 + \frac{0.40}{3} + \frac{0.35}{2} + \frac{0.25}{1} = 0.1333 + 0.175 + 0.25 = 0.5583$$
|
||||
>
|
||||
> **第三步**:计算加速比
|
||||
>
|
||||
> $$S = \frac{1}{T_{new}} = \frac{1}{0.5583} \approx 1.79$$
|
||||
>
|
||||
> **第四步**:分析——如果只改进部件 A(占比最大),加速比为 $1/(0.6+0.4/3) = 1.67$;如果只改进部件 B,加速比为 $1/(0.65+0.35/2) = 1.24$。同时改进 A 和 B 才达到 1.79,说明**改进占比大且加速倍数高的部件收益最大**。
|
||||
|
||||
#### 3.3 CPU 性能公式
|
||||
|
||||
$$CPU 时间 = IC \times CPI \times \tau$$
|
||||
@@ -91,6 +121,31 @@ $$CPU 时间 = IC \times CPI \times \tau$$
|
||||
> [!warning] MIPS 的局限性
|
||||
> 不同指令集的 MIPS 不可直接比较。RISC 机器 MIPS 通常高于 CISC,但不代表性能更优——RISC 需要更多指令完成同样任务。
|
||||
|
||||
> [!example] 例题:两种方案的 CPI 与执行时间对比
|
||||
>
|
||||
> **题目**:同一程序在两种处理器上运行,时钟频率均为 2 GHz,相关参数如下:
|
||||
>
|
||||
> | 参数 | 方案 X | 方案 Y |
|
||||
> |:----:|:------:|:------:|
|
||||
> | 指令条数 IC | 50 亿条 | 10 亿条 |
|
||||
> | 平均 CPI | 1.2 | 5.0 |
|
||||
>
|
||||
> 哪个方案更快?快多少?
|
||||
>
|
||||
> **解**:
|
||||
>
|
||||
> **方案 X**:
|
||||
>
|
||||
> $$T_X = IC \times CPI \times \tau = 5 \times 10^9 \times 1.2 \times \frac{1}{2 \times 10^9} = 3.0 \text{ 秒}$$
|
||||
>
|
||||
> **方案 Y**:
|
||||
>
|
||||
> $$T_Y = 1 \times 10^9 \times 5.0 \times \frac{1}{2 \times 10^9} = 2.5 \text{ 秒}$$
|
||||
>
|
||||
> 方案 Y 更快,加速比为 $T_X / T_Y = 3.0 / 2.5 = 1.2$ 倍。
|
||||
>
|
||||
> **启示**:虽然方案 X 的 CPI 只有 1.2(远低于方案 Y 的 5.0),但方案 Y 的指令条数只有方案 X 的 1/5。这说明**不能只看 CPI 或 IC 单一指标,必须综合考虑三者的乘积**。这也解释了为什么 CISC(IC 少但 CPI 高)和 RISC(IC 多但 CPI 低)可以达到相当的性能水平。
|
||||
|
||||
#### 3.4 程序局部性原理
|
||||
|
||||
程序在执行时所访问的地址空间分布不是随机的,而是**相对地聚集**。
|
||||
@@ -120,6 +175,22 @@ graph LR
|
||||
| MFLOPS | 浮点操作数 / $(T \times 10^6)$ | 科学计算 |
|
||||
| 加速比 | $T_{old} / T_{new}$ | 优化前后对比 |
|
||||
|
||||
> [!tip] CPU 性能公式的三因素关系
|
||||
> CPU 执行时间由三个因素共同决定,优化任何一个因素都能缩短执行时间,但效果取决于瓶颈所在:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
T["CPU Time"] --> IC["IC, Instruction Count"]
|
||||
T --> CPI["CPI, Cycles Per Instruction"]
|
||||
T --> tau["tau, Clock Period"]
|
||||
IC --> C["Compiler"]
|
||||
IC --> ISA["ISA Design"]
|
||||
CPI --> Pipe["Pipeline"]
|
||||
CPI --> Cache["Cache Hit Rate"]
|
||||
tau --> Tech["Process Technology"]
|
||||
tau --> Logic["Logic Design"]
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
- [[计算机系统结构/复习文档/流水线技术]]
|
||||
- [[计算机系统结构/复习文档/存储系统与Cache]]
|
||||
|
||||
Reference in New Issue
Block a user