理解CPU缓存和缓存行

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]的字节。而我们请求的单个字节将位于[08]位置。

3) 如果上述说法正确,那么使用的5位索引是否在技术上不需要,因为所有32字节都在缓存行中?

请告诉我如果我理解错了什么,谢谢。

3个回答

18
缓存由数据和标签 RAM 组成,以访问时间与效率和物理布局的妥协方式排列。你缺少一个重要的统计数据:路数(集合)。你很少有1路缓存,因为它们在简单模式下表现异常糟糕。无论如何:
1)是的,标签需要额外的空间。这是设计妥协的一部分——你不希望它成为总面积的大部分,也不希望行大小只有1个字节或1个字长。此外,一个索引的所有标记同时被访问,如果路数很多,这可能会影响效率和布局。尺寸比您的估计稍微大一些。通常还有一些额外的位来标记有效性和有时提示。更多的路数和较小的行需要更大的标签占用比例,因此通常行很大(32+ 字节),路数很小(4-16)。
2)是的。有些缓存还会进行“关键字优先”抓取,其中它们从导致线路填充的字开始,然后抓取其余的字。这减少了 CPU 等待实际请求的数据的周期数。一些缓存将执行“写直通”,如果在写入时未命中,则不会分配一条线路,这避免了在写入之前必须先读取整个缓存行的情况(这并不总是有利)。
3)标签不会存储低5位,因为它们不需要匹配缓存行。它们只能索引到单独的行中。
维基百科对缓存有一个非常好的、略微复杂的解释:http://en.wikipedia.org/wiki/CPU_cache——请参见“实现”。这里有一个数据和标记如何分割的图表。我认为每个人都应该学习这些东西,因为当你知道底层机器实际上能做什么时,你真的可以提高代码的性能。

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

不同的CPU实现缓存的方式非常不同。为了最好地回答您的问题,请提供有关您所谈论的特定CPU(类型、型号等)的一些附加详细信息。


3
这基于我模糊的记忆,你应该阅读像 Hennessey 和 Patterson 的“计算机体系结构:量化方法”这样的书籍。非常好的书。
假设是32位CPU...(否则你的数字需要使用>4字节(也许<8字节,因为一些/大多数64位CPU没有使用所有64位地址线))用于地址。
1) 我认为至少是4*32字节。根据CPU,芯片架构师可能决定跟踪除完整地址以外的其他信息。但它通常不被视为缓存的一部分。
2) 是的,但映射方式不同。请参见Wikipedia-CPU cache-associativity 这里有简单的直接映射高速缓存和更复杂的关联映射高速缓存。您要避免某些代码需要两个信息,但两个地址映射到完全相同的高速缓存行的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接