目录

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 位。

标记组号块内地址
19b3b6b
  • Cache 地址的结构:

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

组号行号块内地址
3b1b6b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号)(行号)有效位标记位(Tag)数据(行长)
(0)(0)1b19b64B
(0)(1)1b19b64B
(1)(2)1b19b64B
(1)(3)1b19b64B
(...)(...).........
(...)(...).........
(7)(14)1b19b64B
(7)(15)1b19b64B
  • 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 位。

标记组号块内地址
19b3b4b
  • Cache 地址的结构:

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

组号行号块内地址
3b1b4b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号)(行号)有效位标记位(Tag)数据(行长)
(0)(0)1b19b64B
(0)(1)1b19b64B
(1)(2)1b19b64B
(1)(3)1b19b64B
(...)(...).........
(...)(...).........
(7)(14)1b19b64B
(7)(15)1b19b64B
  • 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 位。

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

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

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

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

(组号)(行号)有效位替换控制位脏位标记位(Tag)数据(行长)
(0)(0)1b2b1b20b16B
(0)(1)1b2b1b20b16B
(0)(2)1b2b1b20b16B
(0)(3)1b2b1b20b16B
(1)(4)1b2b1b20b16B
(1)(5)1b2b1b20b16B
(1)(6)1b2b1b20b16B
(1)(7)1b2b1b20b16B
(...)(...).........
(...)(...).........
(15)(62)1b2b1b20b16B
(15)(63)1b2b1b20b16B
  • 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 位。

标记组号块内地址
22b0b6b
  • Cache 地址的结构:

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

行号块内地址
4b6b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号)(行号)有效位标记位(Tag)数据(行长)
(0)(0)1b22b64B
(0)(1)1b22b64B
(0)(2)1b22b64B
(0)(3)1b22b64B
(...)(...).........
(...)(...).........
(0)(14)1b22b64B
(0)(15)1b22b64B
  • 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 位。

标记组号块内地址
24b0b4b
  • Cache 地址的结构:

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

行号块内地址
4b4b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号)(行号)有效位标记位(Tag)数据(行长)
(0)(0)1b24b64B
(0)(1)1b24b64B
(0)(2)1b24b64B
(0)(3)1b24b64B
(...)(...).........
(...)(...).........
(0)(14)1b24b64B
(0)(15)1b24b64B
  • 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 位。

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

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

行号块内地址
4b6b
  • Cache 结构(组号、行号不是 Cache 的组成部分):
(组号)(行号)有效位标记位(Tag)数据(行长)
(0)(0)1b18b64B
(1)(1)1b18b64B
(2)(2)1b18b64B
(3)(3)1b18b64B
(...)(...).........
(...)(...).........
(14)(14)1b18b64B
(15)(15)1b18b64B
  • 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 页):
虚页号页内地址
20b12b
  • 页表结构(虚页号不属于页表结构):
(虚页号)有效位物理页号(页框号)
(0)1b16b
(1)1b16b
(2)1b16b
(3)1b16b
  • 得到的物理地址结构:
物理页号页内地址
16b12b

2.2 快表(TLB)

2.2.1 组相联 TLB

【假设】

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

【则有】

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

2.2.2 全相联 TLB

【假设】

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

【则有】

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

2.2.3 直接相联 TLB

【假设】

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

【则有】

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

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 个不同且位于页面的页号,说明是近期最少使用的页面,把它淘汰。
顺序18172721838327
页 #011111111111117
页 #18888888888888
页 #277777733333
页 #32222222222

综上,失效次数(未命中次数)为 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 组。
组号顺序0482068648
0行 #00088888888
0行 #1444000044
1行 #22222222
1行 #366666

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

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

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

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