缓存存储数据,通常像数据数组一样在 SRAM 中,但也有开销。我并不特别喜欢术语“数据位大小”和“开销位大小”,因为 (a) 存在不是存储位单元的开销,并且 (b) 并非所有位单元都同样昂贵。但现在让我们接受这些条款。
我的看法是,“开销位大小”可能是指为了访问缓存而需要存储的标记位的数量。通常这些存储在不同的数组中,一个与数据数组分开的标签数组。比较数据位数。
这里是三个简单的例子:
考虑一个 32 KiB(千字节)的缓存,以及 64 B(字节)的缓存行。通常,我们会将地址的 0-5 位设为缓存行偏移量。
32 KiB / (64 B/line) => 2^(5+10) / 2^6 => 2^9 => 512 个缓存行。
---++ 示例1:直接映射
让我们想象它是一个直接映射的缓存。然后我们可以将接下来的 9 位,即地址的第 6-14 位,作为缓存行数组的“索引”。
到目前为止一切顺利。现在,要找出标签,我们需要知道完整的地址宽度。假设它是 64 位(尽管截至 2012 年大多数“64 位”机器仅实现 40 或 48 位)。为了区分缓存行与映射到缓存中同一条目的任何其他缓存行,我们需要将地址的剩余位(位 15-63、49 位)存储为标记。
对这种直接映射缓存的访问然后通过提取索引、读取该索引的标签和数据、将读取的标签与我们正在查找的地址的标签进行比较、如果它们匹配则声明命中如果没有,则错过,依此类推。
开销:每 64B(512 位)数据需要 49 位标记。
总计:
* 标签或“开销”:512 * 49 位
* 数据位:512*512 = 32KiB = 256 Kib (kibi-bits)。
---++ 示例 2:8 路集合关联
现在让我们假设缓存是 8 路关联的。这意味着 512 行将分为 512/8 = 64 组,每组包含 8 行。
缓存行内的偏移量仍然是位 0-5。
但是,我们现在只需要 6 位作为索引,就可以确定集合数。位 6-11。
标记需要是所有剩余位,位 12-63,总共 52 位。
因此,8 路关联缓存的标记开销是 512 位数据的 52 位标记。
总计:
* 标签:512 * 52 位
* 数据:512 Kib
比较直接映射的 49 位标记。 8-way set associative 基本上将 log2(8) 更多位移动到标签中;一般来说,N-way set associative 将 ceil(log2(N)) 位移动到标签中。
---++ 示例 3:完全关联
这是直接映射频谱的远端。每个高速缓存行仍然有 512 位数据,但现在整个 64 位地址,除了 6 位偏移量,都是标记。 58 位标记用于完全关联,而 52 位用于 8 路,而 49 位用于直接映射。
但记得我说过我不喜欢“开销位”这个词吗?完全关联高速缓存中的标记位通常不仅是普通存储位,而且还必须具有比较器 - 基本上是 XOR 门。这种“CAM(内容可寻址存储器)”位通常比普通位更昂贵。
---+结论
所以,我认为这就是你的老师想要的:数据位与标签位的直接比较。这是开销的下限。
从直接映射到 N 路集合关联到完全关联的频谱提供了一个示例。但是缓存设计的其他方面也会影响开销。例如:
等等。
教程网站:
抱歉,我不知道有哪一种适合这种初学者的东西。但我会用谷歌搜索许多大学的课堂笔记。
我的网站http://comp-arch.net 涵盖了计算机体系结构的高级主题。但是这种东西太基础了,太初级了,我不能放在 comp.arch 上。虽然我想我应该先写一些对基础知识的简单解释,然后再讨论高级主题。偶尔会写这样的教程,比如这里,但是我没有收集到。
USEnet 新闻组 comp.arch 可能有用。
---+ 为什么这对 stackoverflow 上的程序员很重要?
这主要是硬件话题。
但调优代码的程序员需要了解此类内容,才能获得最佳性能。