G
N
I
D
A
O
L

【组成原理-存储】Cache 和页式虚拟存储器

1 高速缓冲存储器(Cache)

1.1 组相联映射

将 Cache 分为 Q 个大小相等的组,每组有 r 个 Cache行,称为 r 路组相联。

  • Cache 组号 = 主存块号 mod Cache 组数 (Q)

例 1(按字节编址)

【假设】

  • 某计算机的主存地址空间为 256MB,按字节编址(1B),则有 256MB/1B = 256M = 228 个存储单元,地址位数为 28
  • 一个主存块大小为 64B(即 Cache 行长为 64B),则一个主存块的存储单元个数为 64B/1B = 64
  • Cache 有 16 行,又已知 Cache 行长为 64B,二路组相联(即 2 行/组 或 2 块/组),一共 16/2=8 组

【解答】

  • 主存的物理地址的结构:

Cache 一共 23 = 8 组,所以组号占 3 位;主存块(行长)存储单元个数为 26 = 64,所以块内地址占 6 位;因此标记占 28-3-6=19 位。

标记 组号 块内地址
19b 3b 6b
  • Cache 地址的结构:

Cache 的存储单元个数为 64B * 16 / 1B = 1024 = 210,所以 Cache 地址一共 10 位;Cache 一共 23 = 8 组,所以组号占 3 位;每组有两行,所以行号(块号)占 1 位;块内地址占 6 位。

组号 行号 块内地址
3b 1b 6b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号) (行号) 有效位 标记位(Tag) 数据(行长)
(0) (0) 1b 19b 64B
(0) (1) 1b 19b 64B
(1) (2) 1b 19b 64B
(1) (3) 1b 19b 64B
(...) (...) ... ... ...
(...) (...) ... ... ...
(7) (14) 1b 19b 64B
(7) (15) 1b 19b 64B
  • Cache 行位数 = 标记阵列位数 + Cache 行长 = 1 + 19 + 64 * 8 = 532
  • Cache 总位数 = Cache 总行数 * Cache 行位数 = 16 * (1 + 19 + 64 * 8) b = 8512b

【注】Cache 总容量指的是 Cache 的存储容量,不包括标记阵列(标记位、有效位、脏位等),不要与 Cache 总位数搞混!比如某个 Cache 总容量为 64KB,指的是 Cache 存储容量为 64KB,若再加条件:Cache 行长(即主存块大小)为 128B,则该 Cache 总行数为 64KB/128B = 512 行。

例 2(按字编址)

【假设】

  • 某计算机的主存地址空间为 256MB,按字编址(4B),则有 256MB/4B = 64M = 226 个存储单元,地址位数为 26
  • 一个主存块大小为 64B(即 Cache 行长为 64B),则一个主存块的存储单元个数为 64B/4B = 16
  • Cache 有 16 行,又已知 Cache 行长为 64B,二路组相联,一共 16/2=8 组

【解答】

  • 主存的物理地址的结构:

Cache 一共 23 = 8 组,所以组号占 3 位;主存块(行长)存储单元个数为 24 = 16,所以块内地址占 4 位;因此标记占 26-3-4=19 位。

标记 组号 块内地址
19b 3b 4b
  • Cache 地址的结构:

Cache 的存储单元个数为 64B * 16 / 4B = 256 = 28,所以 Cache 地址一共 8 位;Cache 一共 23 = 8 组,所以组号占 3 位;每组有两行,所以行号(块号)占 1 位;块内地址占 4 位。

组号 行号 块内地址
3b 1b 4b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号) (行号) 有效位 标记位(Tag) 数据(行长)
(0) (0) 1b 19b 64B
(0) (1) 1b 19b 64B
(1) (2) 1b 19b 64B
(1) (3) 1b 19b 64B
(...) (...) ... ... ...
(...) (...) ... ... ...
(7) (14) 1b 19b 64B
(7) (15) 1b 19b 64B
  • Cache 行位数 = 标记阵列位数 + Cache 行长 = 1 + 19 + 64 * 8 = 532
  • Cache 总位数 = Cache 总行数 * Cache 行位数 = 16 * (1 + 19 + 64 * 8) b = 8512b

例 3(按字节编址,考虑 LRU 算法、回写策略)

【假设】

  • 某计算机的主存地址空间为 256MB,按字节编址(1B),则有 256MB/1B = 256M = 228 个存储单元,地址位数为 28
  • 一个主存块大小为 16B(即 Cache 行长为 16B),则一个主存块的存储单元个数为 16B/1B = 16
  • Cache 有 64 行,又已知 Cache 行长为 16B,四路组相联,一共 64/4=16 组
  • 考虑 LRU 算法、回写策略(LRU 位的位数与 Cache 组大小有关,2 路时有一位,4 路时有两位

【解答】

  • 主存的物理地址的结构:

Cache 一共 24 = 16 组,所以组号占 4 位;主存块(行长)存储单元个数为 24 = 16,所以块内地址占 4 位;因此标记占 28-4-4=20 位。

标记 组号 块内地址
20b 4b 4b
  • Cache 地址的结构:

Cache 的存储单元个数为 64B * 16 / 1B = 1024 = 210,所以 Cache 地址一共 10 位;Cache 一共 24 = 16 组,所以组号占 4 位;每组有四行,所以行号(块号)占 2 位;块内地址占 4 位。

组号 行号 块内地址
4b 2b 4b
  • Cache 结构(组号、行号不是 Cache 的组成部分):

考虑 LRU 算法,因为是四路组相联,22 = 4,所以替换控制位占 2 位;考虑回写策略,所以脏位占 1 位。(注意:如果题目中没有要求考虑,则不需要加这些东西)

(组号) (行号) 有效位 替换控制位 脏位 标记位(Tag) 数据(行长)
(0) (0) 1b 2b 1b 20b 16B
(0) (1) 1b 2b 1b 20b 16B
(0) (2) 1b 2b 1b 20b 16B
(0) (3) 1b 2b 1b 20b 16B
(1) (4) 1b 2b 1b 20b 16B
(1) (5) 1b 2b 1b 20b 16B
(1) (6) 1b 2b 1b 20b 16B
(1) (7) 1b 2b 1b 20b 16B
(...) (...) ... ... ...
(...) (...) ... ... ...
(15) (62) 1b 2b 1b 20b 16B
(15) (63) 1b 2b 1b 20b 16B
  • Cache 行位数 = 标记阵列位数 + Cache 行长 = 1 + 2 + 1 + 20 + 16 * 8 = 152
  • Cache 总位数 = Cache 总行数 * Cache 行位数 = 64 * (1 + 2 + 1 + 20 + 16 * 8) b = 9728b

1.2 全相联映射

当 Q=1 时变为全相联映射,即整个 Cache 都是一个组。

例 4(按字节编址)

【假设】

  • 某计算机的主存地址空间为 256MB,按字节编址(1B),则有 256MB/1B = 256M = 228 个存储单元,地址位数为 28
  • 一个主存块大小为 64B(即 Cache 行长为 64B),则一个主存块的存储单元个数为 64B/1B = 64
  • Cache 有 16 行,又已知 Cache 行长为 64B

【解答】

  • 主存的物理地址的结构:

主存块(行长)存储单元个数为 26 = 64,所以块内地址占 6 位;因此标记占 28-6=22 位。

标记 组号 块内地址
22b 0b 6b
  • Cache 地址的结构:

Cache 的存储单元个数为 64B * 16 / 1B = 1024 = 210,所以 Cache 地址一共 10 位;Cache 有 16 行,因此块号占 4 位;块内地址占 6 位。

行号 块内地址
4b 6b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号) (行号) 有效位 标记位(Tag) 数据(行长)
(0) (0) 1b 22b 64B
(0) (1) 1b 22b 64B
(0) (2) 1b 22b 64B
(0) (3) 1b 22b 64B
(...) (...) ... ... ...
(...) (...) ... ... ...
(0) (14) 1b 22b 64B
(0) (15) 1b 22b 64B
  • Cache 行位数 = 标记阵列位数 + Cache 行长 = 1 + 22 + 64 * 8 = 279
  • Cache 总位数 = Cache 总行数 * Cache 行位数 = 16 * (1 + 22 + 64 * 8) b = 4464b

例 5(按字编址)

【假设】

  • 某计算机的主存地址空间为 256MB,按字编址(4B),则有 256MB/4B = 64M = 226 个存储单元,地址位数为 26
  • 一个主存块大小为 64B(即 Cache 行长为 64B),则一个主存块的存储单元个数为 64B/4B = 16
  • Cache 有 16 行,又已知 Cache 行长为 64B

【解答】

  • 主存的物理地址的结构:

主存块(行长)存储单元个数为 24 = 16,所以块内地址占 4 位;因此标记占 28-4=24 位。

标记 组号 块内地址
24b 0b 4b
  • Cache 地址的结构:

Cache 的存储单元个数为 64B * 16 / 4B = 256 = 28,所以 Cache 地址一共 8 位;Cache 有 16 行,因此块号占 4 位;块内地址占 4 位。

行号 块内地址
4b 4b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号) (行号) 有效位 标记位(Tag) 数据(行长)
(0) (0) 1b 24b 64B
(0) (1) 1b 24b 64B
(0) (2) 1b 24b 64B
(0) (3) 1b 24b 64B
(...) (...) ... ... ...
(...) (...) ... ... ...
(0) (14) 1b 24b 64B
(0) (15) 1b 24b 64B
  • Cache 行位数 = 标记阵列位数 + Cache 行长 = 1 + 24 + 64 * 8 = 281
  • Cache 总位数 = Cache 总行数 * Cache 行位数 = 16 * (1 + 24 + 64 * 8) b = 4496b

1.3 直接映射

当 r=1 时变为直接映射,即每行 Cache 都是一个组。

  • Cache 组号 = 主存块号 mod Cache 总行数

例 6(按字节编址)

【假设】

  • 某计算机的主存地址空间为 256MB,按字节编址(1B),则有 256MB/1B = 256M = 228 个存储单元,地址位数为 28
  • 一个主存块大小为 64B(即 Cache 行长为 64B),则一个主存块的存储单元个数为 64B/1B = 64
  • Cache 有 16 行,又已知 Cache 行长为 64B

【解答】

  • 主存的物理地址的结构:

Cache 一共 24 = 16 行,所以行号占 4 位;主存块(行长)存储单元个数为 26 = 64,所以块内地址占 6 位;因此标记占 28-4-6=18 位。

标记 行号(组号) 块内地址
18b 4b 6b
  • Cache 地址的结构:

Cache 的存储单元个数为 64B * 16 / 1B = 1024 = 210,所以 Cache 地址一共 10 位;Cache 有 16 行,因此块号占 4 位;块内地址占 6 位。

行号 块内地址
4b 6b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号) (行号) 有效位 标记位(Tag) 数据(行长)
(0) (0) 1b 18b 64B
(1) (1) 1b 18b 64B
(2) (2) 1b 18b 64B
(3) (3) 1b 18b 64B
(...) (...) ... ... ...
(...) (...) ... ... ...
(14) (14) 1b 18b 64B
(15) (15) 1b 18b 64B
  • Cache 行位数 = 标记阵列位数 + Cache 行长 = 1 + 18 + 64 * 8 = 275
  • Cache 总位数 = Cache 总行数 * Cache 行位数 = 16 * (1 + 18 + 64 * 8) b = 4400b

1.4 Cache 命中率的计算

【例 7】有如下 C 语言程序段:

for (k=0; k<1000; k++)
  a[k] = a[k] + 32;

若数组 a 和变量 k 均为 int 型,int 型数据占 4B,数据 Cache 采用直接映射方式,数据区大小是 1KB,块大小是 16B,该程序段执行前 Cache 为空,则该程序段执行过程中,访问数组 a 的 Cache 的缺失率是( )

A. 1.25%

B. 2.5%

C. 12.5%

D. 25%

【解】一个块可以存储 16B / 4B = 4 个 int 型数据,读 4 次、写 4 次,一共访问 8 次,其中第一次未命中,其他 7 次命中。因此 Cache 缺失率为 1 / 8 = 12.5%,选 C。

本题中,Cache 数据区一共有 1KB / 16B = 64 个块,而数组 a 占用 1000 * 4B / 16B = 250 个块,数组 a 占用的块数显然比 Cache 的多,然而本题无需考虑这些因素。这是因为 CPU 将数组 a 的每一个主存块调入 Cache 进行连续访问后,程序后面没有再进行访问,降低了思考和计算难度。

【例 8】数据 Cache 有 8 行,每行大小为 64B。int 型数据用 32 位补码表示。请问程序 A 和程序 B 的命中率是多少?

程序 A:
int a[256][256];
...
int sum_array1 (){
    int i, j, sum = 0;
    for (i=0; i<256; i++)
      for (j=0; j<256; j++)
        sum += a[i][j];
    return sum;
}

程序 B:
int a[256][256];
...
int sum_array2 (){
    int i, j, sum = 0;
    for (j=0; i<256; i++)
      for (i=0; j<256; j++)
        sum += a[i][j];
    return sum;
}

【解】对于程序 A,一个块可以存储 64B / 4B = 16 个 int 型数据,读 16 次,其中第一次未命中,其他 15 次命中。因此 Cache 缺失率为 15 / 16 = 93.75%。

本题中,Cache 数据区一共有 8 个块,而数组 a 占用 256 * 256 * 4B / 64B = 4096 个块,数组 a 占用的块数显然比 Cache 的多,然而本题无需考虑这些因素。这是因为 CPU 将数组 a 的每一个主存块调入 Cache 进行连续访问后,程序后面没有再进行访问,降低了思考和计算难度。

对于程序 B,数组 a 一行占用 256 * 4B / 64B = 16 个块,大于 Cache 数据区的 8 个块,因此在访问完 a[0][0]、a[1][0]、···、a[7][0] 并依次调入这 8 个块到 Cache 后,访问到 a[8][0] 时,必须将 Cache 中的一个块替换掉。所以程序 B 没有一个命中,命中率为 0。

【例 9】某程序运行于一个由 L1、L2 两级 Cache 以及主存组成的存储系统,L1 Cache 和 L2 Cache 的命中率分别为 50% 和 80%,则整个存储系统 Cache 的命中率是( )

A. 65%

B. 80%

C. 90%

D. 95%

【答案】C

【解法一】整个存储系统由两级 Cache 组成,则按照概率论的知识,可以分析出命中的情况有三种:

  • L1 Cache 命中、L2 Cache 命中:50% x 80% = 40%
  • L1 Cache 命中、L2 Cache 不命中:50% x (1-80%) = 10%
  • L1 Cache 不命中、L2 Cache 命中:(1-50%) x 80% = 40%

所以命中率为 40% + 10% + 40% = 90%。

【解法二】逆向思考,先计算不命中的概率:

  • L1 Cache 不命中、L2 Cache 不命中:(1-50%) x (1-80%) = 10%

所以命中率为 1 - 10% = 90%。

2 页式虚拟存储器

2.1 页表

假设虚拟地址空间为 32 位,一页为 4KB,物理地址空间为 28 位,则:

  • 虚拟地址的结构(一共 220 页):
虚页号 页内地址
20b 12b
  • 页表结构(虚页号不属于页表结构):
(虚页号) 有效位 物理页号(页框号)
(0) 1b 16b
(1) 1b 16b
(2) 1b 16b
(3) 1b 16b
  • 得到的物理地址结构:
物理页号 页内地址
16b 12b

2.2 快表(TLB)

2.2.1 组相联 TLB

【假设】

  • 主存空间大小为 256MB,按字节编址,则物理地址位数为 28 位
  • 虚拟地址空间大小为 4GB,页面大小为 4KB,则地址位数为 32 位,有 4GB/4KB = 220 页,所以虚拟地址的虚页号占高 20 位,虚拟地址的页内地址占低 12 位;物理地址的页内地址也占低 12 位,因而物理地址的页号占高 16 位
  • TLB 为二路组相联,一共四组,22=4,则虚页号中组号还要占低 2 位

【则有】

  • (4GB)虚拟地址的结构:
虚页号(标记) 组号 页内地址
18b 2b 12b
  • 二路组相联 TLB 结构(组号、行号不是 TLB 的组成部分):
(组号) (行号) 有效位 标记(Tag) 物理页号(页框号)
(0) (0) 1b 18b 16b
(0) (1) 1b 18b 16b
(1) (2) 1b 18b 16b
(1) (3) 1b 18b 16b
(2) (4) 1b 18b 16b
(2) (5) 1b 18b 16b
(3) (6) 1b 18b 16b
(3) (7) 1b 18b 16b
  • (256MB)得到的物理地址的结构:
物理页号 页内地址
16b 12b

2.2.2 全相联 TLB

【假设】

  • 主存空间大小为 256MB,按字节编址,则物理地址位数为 28 位
  • 虚拟地址空间大小为 4GB,页面大小为 4KB,则地址位数为 32 位,有 4GB/4KB = 220 页,所以虚拟地址的虚页号占高 20 位,虚拟地址的页内地址占低 12 位;物理地址的页内地址也占低 12 位,因而物理地址的页号占高 16 位
  • TLB 为全相联,共 8 行

【则有】

  • (4GB)虚拟地址的结构:
虚页号(标记) 组号 页内地址
20b 0b 12b
  • 四路组相联 TLB 结构(组号、行号不是 TLB 的组成部分):
(组号) (行号) 有效位 标记(Tag) 物理页号(页框号)
(0) (0) 1b 20b 16b
(0) (1) 1b 20b 16b
(0) (2) 1b 20b 16b
(0) (3) 1b 20b 16b
(0) (4) 1b 20b 16b
(0) (5) 1b 20b 16b
(0) (6) 1b 20b 16b
(0) (7) 1b 20b 16b
  • (256MB)得到的物理地址的结构:
物理页号 页内地址
16b 12b

2.2.3 直接相联 TLB

【假设】

  • 主存空间大小为 256MB,按字节编址,则物理地址位数为 28 位
  • 虚拟地址空间大小为 4GB,页面大小为 4KB,则地址位数为 32 位,有 4GB/4KB = 220 页,所以虚拟地址的虚页号占高 20 位,虚拟地址的页内地址占低 12 位;物理地址的页内地址也占低 12 位,因而物理地址的页号占高 16 位
  • TLB 为直接相联,共 8 行,23=8,所以虚页号中行号还要占低 3 位

【则有】

  • (4GB)虚拟地址的结构:
虚页号(标记) 行号 页内地址
17b 3b 12b
  • 直接相联 TLB 结构(组号、行号不是 TLB 的组成部分):
(组号) (行号) 有效位 标记(Tag) 物理页号(页框号)
(0) (0) 1b 17b 16b
(1) (1) 1b 17b 16b
(2) (2) 1b 17b 16b
(3) (3) 1b 17b 16b
(4) (4) 1b 17b 16b
(5) (5) 1b 17b 16b
(6) (6) 1b 17b 16b
(7) (7) 1b 17b 16b
  • (256MB)得到的物理地址的结构:
物理页号 页内地址
16b 12b

3 LRU 替换算法

3.1 直接映射的 LRU 算法

计数器变化规则:

  • 命中时,所命中的行计数器清零,比其低的计数器加 1,其余不变;
  • 未命中且有空闲行时,新装入的行的计数器置 0,其余全加 1;
  • 未命中且无空闲行时,计数值为 3 的行的信息块被淘汰,新装入的行的块计数器置 0,其余全加 1。

【例】内存容量为 4 个页面,使用 LRU 页面替换算法,考虑以下页面访问顺序:{1, 8, 1, 7, 2, 7, 2, 1, 8, 3, 8, 3, 2, 7}

【解答】(斜体表示命中加粗表示该页缺失,需要调入和替换

技巧:无空闲行且需要替换时,从上一次替换的位置开始,从右往左检查页面访问序列,找到第 4 个不同且位于页面的页号,该页号就是要被淘汰的页号。

  • 比如访问该序列到第一个页号 3 时,发现该页缺失,于是从 3 开始逆向检查序列 {7, 2, 1, 8},页号 7 即为第 4 个不同且位于页面的页号,说明是近期最少使用的页面,把它淘汰。
  • 比如访问该序列到最后一个页号 7 时,发现该页缺失,于是从 7 开始逆向检查序列 {1, 8, 3, 8, 3, 2},页号 1 即为第 4 个不同且位于页面的页号,说明是近期最少使用的页面,把它淘汰。
顺序 1 8 1 7 2 7 2 1 8 3 8 3 2 7
页#0 1 1 1 1 1 1 1 1 1 1 1 1 1 7
页#1 8 8 8 8 8 8 8 8 8 8 8 8 8
页#2 7 7 7 7 7 7 3 3 3 3 3
页#3 2 2 2 2 2 2 2 2 2 2

综上,失效次数(未命中次数)为 6 次,命中率为 8/14。

3.2 组相联的 LRU 算法

先计算 Cache 组号 = 主存块号 mod Cache 组数 (Q),看对应的 Cache 组里面有无命中的行,然后按照以下计数器变化规则处理(注意只处理对应组里面的所有行,其他组不用管):

  • 命中时,所命中的行计数器清零,比其低的计数器加 1,其余不变;
  • 未命中且有空闲行时,新装入的行的计数器置 0,其余全加 1;
  • 未命中且无空闲行时,计数值为 3 的行的信息块被淘汰,新装入的行的块计数器置 0,其余全加 1。

【例】Cache 采用二路组相联方式,访问主存地址顺序:{0, 4, 8, 2, 0, 6, 8, 6, 4, 8}

【解答 1:蒋本珊第二版】(斜体表示命中加粗表示该页缺失,需要调入和替换

技巧:无空闲行且需要替换时,从上一次替换的位置开始,从右往左检查页面访问序列,找到第 4 个不同且位于该组页面的页号,该页号就是要被淘汰的页号。

疑问:按唐朔飞教材上看,Cache组号=主存块号 % Cache组数,那上述主存地址不应该都是映射到第0组Cache中吗?为什么答案中有的地址映射到第1组?

  • 主存的 0、1 块对应 Cache 的 0、1 块,也就是 Cache 的第 0 组;
  • 主存的 2、3 块对应 Cache 的 2、3 块,也就是 Cache 的第 1 组;
  • 以此类推,主存的 4、5、8、9 块就对应 0 组,6、7 块对应 1 组;
  • 所以,0、1、4、5、8、9 只能放在 0 组。2、3、6、7 只能放在 1 组。
组号 顺序 0 4 8 2 0 6 8 6 4 8
0 行#0 0 0 8 8 8 8 8 8 8 8
0 行#1 4 4 4 0 0 0 0 4 4
1 行#2 2 2 2 2 2 2 2
1 行#3 6 6 6 6 6

命中次数为 3,命中率为 3/10。

【解答 2:唐朔飞第三版】(斜体表示命中加粗表示该页缺失,需要调入和替换

  • 主存的 0、2、4、6、8 块对应 Cache 的 0、1 块,也就是 Cache 的第 0 组;
  • 主存的 1、3、5、7、9 块对应 Cache 的 0、1 块,也就是 Cache 的第 1 组。
组号 顺序 0 4 8 2 0 6 8 6 4 8
0 行#0 0 0 8 8 0 0 8 8 4 4
0 行#1 4 4 2 2 6 6 6 6 8
1 行#2
1 行#3

命中次数为 1,命中率为 1/10。

posted @ 2022-08-23 17:47  漫舞八月(Mount256)  阅读(1318)  评论(0编辑  收藏  举报