【问题标题】:What Are Conflict Misses Exactly?究竟什么是冲突未命中?
【发布时间】:2021-11-13 06:57:54
【问题描述】:

我正在学习基本的缓存概念和不同类型的缓存未命中。我了解未命中的强制类型,但我很难理解未命中的冲突和容量类型!我仍然需要了解缓存的替换算法。我已经阅读了本网站上有关此主题的其他问题,但关于这些其他问题的信息在容量和冲突未命中方面一直存在冲突或含糊不清。我希望在这个问题上我的问题能得到解答。

例如,假设我们有一个包含 4 个集合的 2 路关联缓存。先说第一组可以存储两个缓存行/块(因为它是路关联缓存)。我现在将列出从处理器调用的读取顺序。为简单起见,所有这些正在读取的地址都将落入第一组。

-read address one (no cache line in set one for this address. This would be a compulsory cache miss. Data is copied from memory to the first cache line in this set).

-read address two (no cache line in set one for this address. This would also be a compulsory cache miss. Data is copied from memory to the second cache line in this set).

第一组缓存现在已“预热”,这意味着该组已满容量,其中包含有效的缓存行。现在让我们尝试访问一个也属于第一组的地址。

-read address three (no cache line in set one for this address. Out of space in set one for anymore cache lines to be written.)

我们遇到了一个问题,即试图从内存中获取一条新的缓存线到第一组,但第一组完全被两条缓存线占用。在这种情况下,您必须使用缓存替换策略。这个问题在直接映射缓存中非常普遍。缓解这个问题的方法是增加每个集合的关联性(意味着增加可以存储在一个集合中的缓存行的数量)。

我的问题是,这种情况是强制性的还是冲突的失误?或者冲突未命中会影响所有系列?有什么区别?在我上面写的示例中,它们每个人将如何工作?如前所述,网站上的其他问题对我来说真的没有意义,所以我希望我能尽快解决这个问题。

【问题讨论】:

  • 你为什么要标记这个 [x86] [arm]?您是否对其中一个 ISA 的特定微架构感兴趣,比如 Zen 3、Ice Lake 或 Cortex-A57,它们的硬件预取器可能会执行额外的提取,这可能会导致驱逐更多数据以为预取腾出空间(即冲突)?还是他们的多级每核和共享缓存?从问题的文字来看,我猜不是,所以我删除了这两个标签以为 [cpu-cache] 腾出空间,但如果有相关内容,请编辑。
  • compulsive - 正确的术语是 compulsory,即强制/必需,无法避免。希望您的 CPU 不会沉迷于缓存未命中。 :P
  • @Vatine:为什么你认为 [computer-science] 标签不适用于这个问题?它显然是关于简单(甚至过度简化)硬件作为研究缓存的一种方式,而不是真实世界的工程。以及一个没有内存级并行性的简单执行模型。它是关于计算机科学中用于描述缓存行为的术语,而不是关于编程。 OTOH,我们确实已经有 [computer-architecture] 和 [cpu-cache] 标签,所以人们不需要 need [cs] 来找到它,但它是否会弄乱 [cs]以某种方式标记?
  • @PeterCordes 我真的没有看到任何与我认为是“计算机科学”相关的问题(这实际上与硬件无关,基本上是应用数学的一个分支) .
  • @Vatine:请注意,[computer-science-theory] ​​有一个单独的标签。我猜你认为这是一个错误,并且任何一个标签都应该只用于 Big-O 复杂性、阿姆达尔定律等问题,而不是用于计算机体系结构的理论部分?

标签: caching cpu-architecture cpu-cache


【解决方案1】:

首先,我将给出这些术语的精确定义,这些术语最初在 Mark Donald Hill's dissertation 中引入,然后我将给出更常见的松散定义。

考虑具有以下特征的缓存:

  • 它不支持硬件预取。由于传入的请求,行只能填充到缓存中。
  • 它是阻塞的,这意味着它不会在当前请求完全完成之前开始处理请求。
  • 只有一个代理(即处理器)可以更改缓存的内容。系统中的任何其他单元都不会导致生产线失效、更换或填充。
  • 所有未命中的缓存访问都会导致目标缓存行被完全提取并填充到缓存中。
  • 现有缓存行被驱逐或失效的唯一方法是腾出空间来填充另一个缓存行。否则,它将在缓存中始终处于有效状态。

T 为不跨越行边界的访问序列,并且所有这些访问都是按需访问(没有软件预取,也没有来自较低编号缓存级别的硬件预取,如果有的话) .每次访问都算作一次未命中或命中。令 M(N, S) 表示具有上述所有特征的缓存中发生的未命中次数,其中 N 是路数,S 是集合的数量。请注意,M(N, S) 必须是非负整数,NS 必须是正整数。这是正在评估的缓存。可以基于它定义另外两种缓存模型。令 M(N*S, 1) 表示缓存中发生的未命中数,除了它有 N*S 个路和一组.最后,让 M(∞, 1) 表示缓存中发生的未命中次数,该缓存在所有方式上都相同,除了它有无限数量的方式和一个集合(集合的数量不在这里并不重要)。

现在想象一下,所有三个缓存模型都在使用相同的输入并行模拟,T,并且所有缓存都是空的(即冷启动)。 强制未命中是在具有无限多个缓存方式的缓存中发生的缓存未命中。当且仅当它是 T 中对同一缓存行的第一次访问时,无限缓存中的访问未命中。如果在无限模型中发生强制未命中,那么其他两个模型中也必然会发生。强制未命中数为M(∞, 1),为非负数。

容量未命中是在完全关联模型中发生的缓存未命中,但在无限容量模型中不会发生。因此,容量未命中数为M(N*S, 1) - M(∞, 1),是非负数。当且仅当访问不是对高速缓存行的第一次访问并且替换策略已选择要由先前访问的行替换的行时,才会在完全关联模型中发生容量丢失。例如,如果替换策略是 LRU,当且仅当访问不是对缓存行的第一次访问并且到目前为止访问的唯一缓存行的总数超过缓存的容量时,才会发生容量丢失。

冲突未命中是在所研究的模型中发生的缓存未命中,但在完全关联模型和无限容量模型中均未发生。当且仅当它不是容量未命中且不是强制未命中时,未命中才是冲突未命中。如果正在研究的模型是完全关联的,则冲突未命中的数量为零。最初定义的冲突未命中数为M(N, S) - M(N*S, 1)。仅当在完全关联模型中丢失的所有访问在主模型中也丢失时,此数量才是非负的。虽然两个模型中的强制缺失是相同的,但并非所有在完全关联模型中缺失的其他访问也会在主模型中缺失,反之亦然。这取决于更换政策。例如,请参阅:Can a fully associative cache have a higher miss rate than a direct mapped cache?。因此,冲突未命中的数量可能为负数。但是如果以任何其他方式计算冲突未命中的数量,则所有三种类型的未命中计数的总和可能大于未命中的总数。

凭借开头提供的特性,没有其他类型的未命中。我想出了这个特征列表。论文中没有提到它们,因为当时大多数缓存设计都很简单,而且无论如何都有这些特点。但实际系统中使用的更现代的缓存更复杂。

现在您应该可以根据您自己示例中的访问“读取地址三”来确定未命中的类型。

当人们使用“冲突缺失”和“容量缺失”这两个词时,他们并不是指这些精确的定义,而是在精神上指代这些定义,这种情况并不少见。可以通过更改正在访问的数据结构的布局来减少冲突未命中。可以通过减小工作集大小来减少容量缺失。当您想在真实处理器上测量这些指标时,您必须根据受支持的性能监控功能来定义它们,而您无法像在模拟器中那样扩展这些功能。

在实验评估环境中使用这些术语时,准确定义这些术语很重要,因为它们没有标准定义。否则,它们将是模棱两可的,没有人能确定测量的是什么。如果在没有数字的讨论中使用,那么松散使用是可以的,因为每个人都知道他们在精神上的意思。

我已阅读本网站上有关此主题的其他问题,但是 关于这些其他问题的信息相互矛盾或含糊不清 关于容量和冲突失误。

如果您提供这些帖子的链接,那就太好了。如果其他人发布了一个很好的答案并且可能只需要很小的改进,那么就没有必要从头开始写一个。否则,其中一些可以作为重复项关闭,以便像您这样试图获得答案的其他人可以直接指向正确的答案,而无需每个人都费力地穿过混乱。

【讨论】:

    猜你喜欢
    • 2018-01-29
    • 2014-09-11
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2014-10-28
    • 2012-08-27
    • 2010-11-12
    相关资源
    最近更新 更多