【问题标题】:How does direct mapped cache work?直接映射缓存如何工作?
【发布时间】:2013-04-02 22:51:58
【问题描述】:

我正在学习系统架构课程,但我无法理解直接映射缓存的工作原理。

我看过几个地方,他们以不同的方式解释它,这让我更加困惑。

我不明白的是什么是标签和索引,它们是如何选择的?

我讲座的解释是: “地址分为两部分 用于直接寻址 (32k) RAM 的索引(例如 15 位) 地址的其余部分,标签被存储并与传入的标签进行比较。 "

这个标签是从哪里来的?它不能是 RAM 中内存位置的完整地址,因为它使直接映射缓存无用(与完全关联缓存相比)。

非常感谢。

【问题讨论】:

标签: caching system cpu-architecture


【解决方案1】:

好的。所以我们先来了解一下 CPU 是如何与缓存交互的。

内存分为三层(广义上​​)——cache(一般由SRAM芯片制成)、main memory(一般由DRAM芯片制成)、storage(一般是磁性的,像硬磁盘)。每当 CPU 需要来自某个特定位置的任何数据时,它首先会搜索缓存以查看它是否存在。缓存在内存层次结构上最接近 CPU,因此它的访问时间最短(成本最高),因此如果 CPU 正在寻找的数据可以在那里找到,则构成“命中”,并且数据从那里获得供 CPU 使用。如果不存在,则必须将数据从主存移至缓存,然后才能被 CPU 访问(CPU 通常只与缓存交互),这会导致时间损失。

因此,为了找出缓存中是否存在数据,需要应用各种算法。一种是这种直接映射缓存方法。为简单起见,我们假设一个内存系统有 10 个可用的高速缓存内存位置(编号为 0 到 9)和 40 个可用的主内存位置(编号为 0 到 39)。这张图总结了一下:

有 40 个可用的主内存位置,但缓存中最多只能容纳 10 个。所以现在,通过某种方式,来自 CPU 的传入请求需要重定向到缓存位置。这有两个问题:

  1. 如何重定向?具体来说,如何以一种不会随着时间而改变的可预测方式来做到这一点?

  2. 如果缓存位置已经被一些数据填满,来自 CPU 的传入请求必须识别它需要数据的地址是否与数据存储在该位置的地址相同。

在我们的简单示例中,我们可以通过简单的逻辑进行重定向。假设我们必须将 40 个从 0 到 39 连续编号的主内存位置映射到 10 个编号为 0 到 9 的缓存位置,内存位置n 的缓存位置可以是n%10。所以 21 对应 1,37 对应 7,以此类推。这成为 index

但是 37、17、7 都对应 7。所以为了区分它们,就来了 标签。所以就像索引是n%10,标签是int(n/10)。所以现在 37、17、7 会有相同的索引 7,但是 3、1、0 等不同的标签。也就是说,映射可以完全由标签和索引这两个数据指定。

所以现在如果请求地址位置 29,那将转换为标签 2 和索引 9。索引对应于缓存位置编号,因此缓存位置编号。将查询 9 以查看它是否包含任何数据,如果是,则关联的标签是否为 2。如果是,则 CPU 命中,将立即从该位置获取数据。如果它是空的,或者标签不是2,这意味着它包含与其他一些内存地址对应的数据,而不是29(虽然它会有相同的索引,这意味着它包含来自9、19这样的地址的数据, 39 等)。所以这是一个 CPU 未命中,并且来自位置号的数据。主存中的 29 必须加载到位置 9 的缓存中(并且标记更改为 2,并删除之前存在的所有数据),然后由 CPU 获取。

【讨论】:

  • @SibbsGambling 找到块后,偏移量用于指定我们想要在其中的哪个字节。
  • 迄今为止最好的解释
  • “移动”实际上是指“复制”。
  • 感谢您的宝贵帖子!
  • @SexyBeast 我相信这个“​​......以及来自主内存中第 29 号位置的数据必须加载到位置 29 的缓存中”应该被替换通过“...要加载到位置 9 的缓存中”。
【解决方案2】:

让我们举个例子。一个 64 KB 的缓存,具有 16 字节的缓存线,有 4096 个不同的缓存线。

您需要将地址分成三个不同的部分。

  1. 最低位用于在您取回缓存行时告诉您缓存行中的字节,这部分不直接用于缓存查找。 (本例中的位 0-3)
  2. 下一位用于索引缓存。如果您将缓存视为一大列缓存行,则索引位会告诉您需要在哪一行中查找数据。 (本例中的第 4-15 位)
  3. 所有其他位都是 TAG 位。这些位存储在您存储在缓存中的数据的标签存储中,我们将缓存请求的相应位与我们存储的数据进行比较,以确定我们正在缓存的数据是否是正在请求的数据。

您用于索引的位数是 log_base_2(number_of_cache_lines) [确实是集合数,但在直接映射缓存中,行数和集合数相同]

【讨论】:

  • 我想我明白了,但我现在还有另一个问题。到目前为止,我认为这是一个单独的表,应该以某种方式存储地址和数据。在我看来,这个缓存最好用 3 个表来表示:一个是带有缓存行的表,带有 TAG、INDEX 和选择位,一个是标签存储,一个是数据存储。当 CPU 试图访问一个位置时,它会检查 TAG 以查看它是否是它正在寻找的地址,它检查它是否仍然有效,然后它使用 INDEX 从数据存储加载数据。
  • @Percentage 我不认为你明白了。只有两张桌子。一个用于标签,另一个用于数据。两者都使用相同的索引,即您可以认为它们只是一张表。这就是你所需要的。想想吧。
  • @MackieMesser 只是为了确保我理解。每个 Cache 行都有不同的 TAG 位来标识缓存行中的字节来自 RAM 中的哪个位置?
  • @committedandroider 不仅仅是 TAG 位,还有 TAG 和 INDEX 位的组合告诉您高速缓存行在主内存中的位置。巧妙的是,您不需要实际存储 INDEX 位,因为它们对于特定的缓存行总是相同的。
  • @MackieMesser 就像 Danny 上面所说的那样,从我了解到的情况来看,索引行不只是为了在您拥有缓存地址时识别数据所在的缓存行吗?它不应该与主存有任何关系。
【解决方案3】:

直接映射缓存就像一个表,其中包含行(也称为缓存行)和至少 2 列,一列用于数据,另一列用于标记。

它是这样工作的:对缓存的读取访问将地址的中间部分称为索引并将其用作行号。同时查找数据和标签。 接下来,需要将该标记与地址的上半部分进行比较,以确定该行是否来自内存中的同一地址范围并且有效。同时,地址的下半部分可以用来从缓存行中选择请求的数据(我假设一个缓存行可以保存几个字的数据)。

我强调了一点数据访问和标签访问+比较同时发生,因为这是减少延迟的关键(缓存的目的)。数据路径ram访问不需要两步。

优点是读取基本上是一个简单的表查找和比较。

但它是直接映射的,这意味着对于每个读取地址,缓存中只有一个位置可以缓存此数据。所以缺点是很多其他地址会被映射到同一个地方,可能会竞争这个缓存行。

【讨论】:

  • 谈论并行性:直接映射缓存的一个值得注意的特性是标签路径和数据路径是独立的。在标签路径中,读取标签和将标签与地址进行比较是产生命中/未命中信号的两个顺序操作。在数据路径中,只有一项操作。地址的中部和下部形成数据 RAM 的单个地址,以产生单个输出字。 RAM 内部的组织方式并不重要。
  • 是的,感谢您指出这一点。我在数据路径中描述的两个步骤只是ram的一个实现细节。
  • @deepsubmicron 你能详细介绍一下地址的上下部分吗?您如何识别下部是什么,上部是什么?
  • 内存有多宽?高速缓存行中的字数,即地址的较低部分。中间部分由 ram 中的行数决定。所以剩下的就是上半部分了。
【解决方案4】:

我在图书馆找到了一本好书,它为我提供了我需要的清晰解释,现在我将在这里分享它,以防其他学生在搜索缓存时偶然发现这个线程。

这本书是 Hennesy 和 Patterson 所著的“计算机体系结构 - 一种定量方法”第 3 版,第 390 页。

首先,请记住,主内存被划分为用于缓存的块。 如果我们有一个 64 字节的缓存和 1 GB 的 RAM,那么 RAM 将被划分为 128 KB 的块(1 GB 的 RAM / 64B 的缓存 = 128 KB 块大小)。

从书中:

块可以放在缓存中的什么位置?

  • 如果每个块在缓存中只能出现一个位置,则称缓存为直接映射。使用以下公式计算目标块:<RAM Block Address> MOD <Number of Blocks in the Cache>

所以,假设我们有 32 块 RAM 和 8 块缓存。

如果我们要将 RAM 中的第 12 块存储到缓存中,那么 RAM 块 12 将存储到缓存块 4 中。为什么?因为 12 / 8 = 1 余数 4。余数就是目标块。

  • 如果可以将块放置在缓存中的任何位置,则称缓存是完全关联的

  • 如果一个块可以放置在缓存中有限的一组位置中的任何位置,则缓存是设置关联的

基本上,集合是缓存中的一组块。一个块首先映射到一个集合上,然后该块可以放置在集合内的任何位置。

公式为:<RAM Block Address> MOD <Number of Sets in the Cache>

因此,假设我们有 32 块 RAM 和一个缓存,分为 4 组(每组有 2 个块,意味着总共 8 个块)。这样设置 0 将具有块 0 和 1,设置 1 将具有块 2 和 3,依此类推...

如果我们要将 RAM 块 12 存储到缓存中,RAM 块将存储在缓存块 0 或 1 中。为什么?因为 12 / 4 = 3 余数为 0。因此选择了集合 0,并且该块可以放置在集合 0 内的任何位置(即块 0 和 1)。

现在我将回到我最初的地址问题。

如果块在缓存中,如何找到它?

缓存中的每个块帧都​​有一个地址。只是为了说清楚,一个块既有地址又有数据。

块地址分为多个部分:Tag、Index和Offset。

标签用于查找缓存内的块,索引仅显示块所在的集合(使其非常冗余),偏移量用于选择数据。

“选择数据”是指在一个缓存块中显然会有多个内存位置,偏移量用于在它们之间进行选择。

所以,如果您想想象一个表格,这些列将是:

TAG | INDEX | OFFSET | DATA 1 | DATA 2 | ... | DATA N

标签将用于查找块,索引将显示块在哪个集合中,偏移量将选择其右侧的字段之一。

希望我的理解是正确的,如果不是请告诉我。

【讨论】:

  • 这是错误的。该表只包含标签和数据,不包含索引和偏移量。
  • 我从这个链接得到了一个很好的答案:csciwww.etsu.edu/tarnoff/labs4717/x86_sim/direct.html
  • 索引和偏移量对应表中的位置。它们没有明确存储。我敢肯定轩尼诗和帕特森正确地解释了它,因为那本教科书非常出色且众所周知,但是您在此答案中弄乱了它的最后一点。
  • 另外,索引并不像你说的那样多余,它是必不可少的。您不仅仅使用标签来查找缓存中的块。您同时使用标签和索引。
猜你喜欢
  • 2015-08-20
  • 2018-06-24
  • 2018-05-24
  • 2014-06-04
  • 2020-04-18
  • 2019-05-16
  • 2012-07-09
  • 1970-01-01
相关资源
最近更新 更多