26

我试图了解 CPU 缓存是如何运行的。假设我们有这个配置(例如)。

  • 缓存大小 1024 字节
  • 高速缓存行 32 字节
  • 1024/32 = 总共 32 条缓存线。
  • 单个缓存行可以存储 32/4 = 8 个整数。

1)根据这些配置,标签长度应为 32-5=27 位,索引大小为 5 位(2^5 = 缓存行中每个字节的 32 个地址)。

如果总缓存大小为 1024,并且有 32 个缓存行,那么标签+索引存储在哪里?(还有另外4*32 = 128字节。)是不是表示缓存的实际大小是1024+128 = 1152?

2) 如果在这个例子中缓存线是 32 字节,这意味着每当 CPU 需要从 RAM 中获取新字节时,32 字节就会被复制到缓存中。我是否正确假设所请求字节的缓存行位置将由其地址确定?

这就是我的意思:如果 CPU 请求的字节位于[FF FF 00 08],那么可用的缓存行将被从[FF FF 00 00]到的字节填充[FF FF 00 1F]。我们请求的单个字节将位于 position [08]

3)如果前面的语句是正确的,这是否意味着用于索引的 5 位在技术上是不需要的,因为所有 32 字节都在缓存行中?

如果我有什么问题,请告诉我。谢谢

4

3 回答 3

17

缓存由数据和标记 RAM 组成,排列为访问时间与效率和物理布局的折衷。你错过了一个重要的统计数据:方式(组)的数量。您很少有单向缓存,因为它们在简单模式下表现得很糟糕。反正:

1) 是的,标签占用额外空间。这是设计妥协的一部分——您不希望它占总面积的很大一部分,以及为什么行大小不仅仅是 1 个字节或 1 个字。此外,索引的所有标签都是同时访问的,如果有很多方法,这会影响效率和布局。尺寸略大于您的估计。通常还有一些额外的位来标记有效性,有时还有提示。更多的方式和更小的行需要标签占据更大的比例,所以通常行很大(32+字节)而方式很小(4-16)。

2) 是的。一些缓存还进行“关键字优先”提取,它们从导致行填充的字开始,然后提取其余部分。这减少了 CPU 等待它实际请求的数据的周期数。如果您错过写入,某些缓存将“直通”并且不会分配行,这避免了在写入之前必须先读取整个缓存行(这并不总是胜利)。

3) 标签不会存储低 5 位,因为它们不需要匹配缓存行。他们只是索引到单独的行。

Wikipedia 有一篇关于缓存的文章(如果有点激烈的话)相当不错:http ://en.wikipedia.org/wiki/CPU_cache - 请参阅“实施”。有一张关于如何拆分数据和标签的图表。我,我认为每个人都应该学习这些东西,因为当你知道底层机器的实际能力时,你真的可以提高代码的性能。

于 2011-02-15T18:05:25.207 回答
3
  1. 缓存元数据通常不计为缓存本身的一部分。它甚至可能不存储在 CPU 的同一部分(它可能在另一个缓存中,使用特殊的 CPU 寄存器等实现)。
  2. 这取决于您的 CPU 是否会获取未对齐的地址。如果它只会获取对齐的地址,那么您给出的示例将是正确的。如果 CPU 获取未对齐的地址,那么它可能会获取 0xFFFF0008 到 0xFFFF0027 的范围。
  3. 即使缓存访问是对齐的,索引字节仍然有用。这为 CPU 提供了一种简写方法,用于引用高速缓存行中的字节,它可以在其内部簿记中使用。您可以通过知道与高速缓存行关联的地址和与字节关联的地址来获得相同的信息,但要携带的信息要多得多。

不同的 CPU 实现缓存的方式非常不同。为了获得您问题的最佳答案,请提供有关您正在谈论的特定 CPU(类型、型号等)的一些其他详细信息。

于 2011-02-15T18:05:46.467 回答
3

这是基于我模糊的记忆,您应该阅读 Hennessey 和 Patterson 的“计算机架构:定量方法”之类的书。很棒的书。

假设一个 32 位 CPU ...(否则您的数字将需要使用 >4 字节(可能 <8 字节,因为某些/大多数 64 位 CPU 没有使用所有 64 位地址线))作为地址。

1)我相信它至少是 4*32 字节。根据 CPU 的不同,芯片架构师可能已经决定跟踪除完整地址之外的其他信息。但它通常不被视为缓存的一部分。

2) 是的,但是映射的完成方式不同。参见Wikipedia - CPU cache - associativity有简单的直接映射缓存和更复杂的关联映射缓存。您希望避免某些代码需要两条信息但两个地址映射到完全相同的缓存行的情况。

于 2011-02-15T18:05:51.487 回答