Cache 映射方式决定了主存地址如何映射到 Cache 中。主要有三种:直接映射、组相联映射和全相联映射。它们在速度、成本和复杂度上各有权衡。
1. 直接映射 (Direct Mapping)
原理: 每个主存块只能映射到 Cache 的一个特定位置。 主存地址被分成三个部分:块偏移 (Block offset)、索引 (Index) 和标记 (Tag)。索引决定 Cache 行的位置,标记用于验证主存块是否在该 Cache 行中。如果索引和标记都匹配,则缓存命中 (cache hit);否则,缓存不命中 (cache miss)。
公式: 假设主存地址为 A,Cache 有 C 行,每行大小为 B 字节。则:
块偏移:offset=log 2 B 位
索引index=log 2 C 位
标记:Tag=A−index−offset 位
优点: 简单、成本低。
缺点: 命中率最低。如果多个主存块映射到同一个 Cache 行,即使它们很少同时被访问,也会发生冲突,导致频繁的缓存不命中。
2. 组相联映射 (Set-Associative Mapping)
原理: 将 Cache 分成多个组 (Set),每个组包含多个行。主存块根据索引映射到特定的组,然后在该组内进行匹配。组内采用全相联的方式进行查找。
公式: 假设 Cache 有 S 组,每组有 E 行,每行大小为
B 字节。则:
块偏移:offset=log 2 B 位
组索引:index=log 2 S 位
标记:Tag=A−index−offset 位
优点: 命中率比直接映射高,比全相联映射低。
缺点: 比直接映射复杂,成本较高。
3. 全相联映射 (Fully Associative Mapping)
原理: 任何主存块都可以映射到 Cache 的任何一行。需要对所有 Cache 行进行比较才能确定是否命中。
公式: 主存地址分为标记 (Tag) 和块偏移 (Block offset) 两部分。
块偏移:
offset=log 2 B 位
标记:Tag=A−offset 位
优点: 命中率最高。
缺点: 实现复杂,成本非常高,查找速度慢。
Cache 标记阵列与存储容量
除了数据和有效位 (Valid bit) 外,Cache 标记阵列通常还需要以下位:
脏位 (Dirty bit): 指示 Cache 行中的数据是否被修改过。如果脏位为 1,则需要将修改后的数据写回主存。
替换控制位 (Replacement control bits): 用于替换策略,例如 LRU (Least Recently Used) 位或其他算法,决定哪个块被替换。
有效位 (Valid bit): 指示该 Cache 行是否包含有效数据。
例题:
假设一个 Cache 容量为 1KB,块大小为 16 字节,采用 2 路组相联映射。主存地址空间为 32 位。
计算 Cache 的参数:
块大小:16 字节 = 24 字节,块偏移 = 4 位
Cache 容量:1KB = 210 字节
每组行数:2 路, E = 2
组数:S= 2 10/2×24=32 组,组索引 =log 2 32=5 位
标记位数:Tag=32−4−5=23 位
地址映射: 假设主存地址为 0x00001F2A (十进制 12938)。
块偏移:2A 的后 4 位 A (1010)
组索引:1F2 的后 5 位 00111110 (十进制 62)。由于有 32 组,62 超过范围,实际取62 mod 32 = 30,即 11110
标记:00001F (十进制 31)
因此,该主存块映射到 Cache 的第 30 组,标记为 31。 Cache 控制器需要检查第 30 组的两个行,查看是否有标记为 31 的行。
其他替换算法:
除了 LRU,常用的替换算法还有:
FIFO (First In First Out): 先进入 Cache 的块先被替换。
Random: 随机选择一个块进行替换。
总结:
选择合适的 Cache 映射方式取决于应用场景的访问模式和成本约束。直接映射简单廉价但命中率低,全相联映射命中率高但成本高,组相联映射是折中方案,其性能和成本都介于两者之间。 选择合适的替换算法也能提升 Cache 的效率。