【问题标题】:What cache invalidation algorithms are used in actual CPU caches?实际 CPU 缓存中使用了哪些缓存失效算法?
【发布时间】:2014-05-01 02:19:20
【问题描述】:

我谈到了缓存和映射以及缓存未命中以及缓存块如何在所有块都已满时以什么顺序被替换的主题。

有最近最少使用的算法或者fifo算法或者最不频繁的算法和随机替换,...​​

但是在实际的 cpu 缓存上使用了哪些算法?或者你可以使用所有的......操作系统决定最好的算法是什么?


编辑:即使我选择了答案,也欢迎任何进一步的信息;)

【问题讨论】:

  • 我猜其中很多都是商业机密......所以我不确定你会在这里得到一个非常准确的答案。

标签: algorithm caching cpu-cache


【解决方案1】:

正如 hivert 所说 - 很难对具体算法有一个清晰的了解,但可以根据提示或巧妙的逆向工程推断出一些信息。

您没有指定您的意思是哪个 CPU,每个 CPU 可以有不同的策略(实际上即使在同一个 CPU 内,不同的缓存级别也可能有不同的策略,更不用说 TLB 和其他也可能有此类策略的关联数组) .我确实找到了一些关于英特尔(特别是 Ivy 桥)的提示,因此我们将使用它作为行业级“标准”的基准(可能适用于其他地方,也可能不适用)。

首先,英特尔在这里展示了一些与 LRU 相关的特性—— http://www.hotchips.org/wp-content/uploads/hc_archives/hc24/HC24-1-Microprocessor/HC24.28.117-HotChips_IvyBridge_Power_04.pdf

幻灯片 46 提到了“Quad-Age LRU”——这显然是一个基于年龄的 LRU,它根据预测的重要性为每行分配了一些“年龄”。他们提到预取进入中年,因此需求可能分配在更高的年龄(或更低的年龄,任何存活时间最长的),并且所有行可能逐渐老化,所以最旧的首先被替换。不如完美的“fifo-like”LRU,但请记住,大多数缓存都没有实现这一点,而是一个复杂的pseudo-LRU 解决方案,所以这可能是一种改进。

这里提到的另一个有趣的机制是自适应填充策略,它比经典的 LRU 更进一步。这里有一个很好的分析 - http://blog.stuffedcow.net/2013/01/ivb-cache-replacement/ ,但简而言之(如果博客是正确的,并且他似乎确实与他的结果很好地匹配),缓存在两个 LRU 策略之间动态选择,试图决定是否行将被重用或不被重用(应该保留或不保留)。

我想这可以在一定程度上回答您关于多个 LRU 方案的问题。就硬件而言,实施多个方案可能既困难又昂贵,但是当您有一些复杂到足以具有参数的策略时,可以使用动态选择、集合决斗等技巧。

【讨论】:

    【解决方案2】:

    以下是实际处理器中使用的替换策略的一些示例。

    PowerPC 7450 的 8 路 L1 缓存使用二叉树 pLRU。二叉树 pLRU 使用每对方式一个位来为该对设置一个 LRU,然后为每一对 方式对 设置一个 LRU 位,等等。8 路 L2 使用伪随机替换可设置由特权软件(操作系统)作为使用每个时钟周期递增的 3 位计数器或基于移位寄存器的伪随机数生成器。

    StrongARM SA-1110 32 路 L1 数据缓存使用 FIFO。它还有一个用于瞬态数据的 2-way minicache,它似乎也使用了 FIFO。 (Intel StrongARM SA-1110 Microprocessor Developer's Manual 声明“minicache 中的替换使用与主数据缓存中相同的循环指针机制。但是,由于此缓存仅是双向集合关联,替换算法简化为一个简单的最近最少使用 (LRU) 机制。”;但是即使只有两种方式,2 路 FIFO 也 与 LRU 相同,尽管它适用于流数据一样的。])

    HP PA 7200 有一个 64 块的完全关联“辅助缓存”,可与片外直接映射数据缓存并行访问。辅助缓存使用 FIFO 替换,并可选择驱逐到片外 L1 缓存。加载和存储指令具有“仅局部性”提示;如果这样的内存访问加载了辅助缓存条目,它将绕过片外 L1 被逐出到内存中。

    对于 2-way associativity,真正的 LRU 可能是最常见的选择,因为它具有良好的行为(顺便提一下,当只有两种方法时,它与二叉树 pLRU 相同)。例如,Fairchild Clipper 缓存和内存管理单元使用 LRU 作为其 2 路缓存。 FIFO 比 LRU 稍微便宜一些,因为替换信息只在标签被写入时更新,即插入新的缓存块时,但比基于计数器的伪随机替换具有更好的行为(其开销甚至更低)。 HP PA 7300LC 将 FIFO 用于其 2 路 L1 缓存。

    Itanium 9500 系列 (Poulson) 将 NRU 用于 L1 和 L2 数据高速缓存、L2 指令高速缓存和 L3 高速缓存(L1 指令高速缓存记录为使用 LRU。)。对于 Itanium 2 6M (Madison) 中的 24 路 L3 高速缓存,为 NRU 提供了每块一个位,可以访问一个块设置与其设置和路相对应的位(“Itanium 2 Processor 6M: Higher Frequency and Larger L3 缓存”,Stefan Rusu 等人,2004 年)。这类似于时钟页面替换算法。

    我似乎记得在其他地方读过,当所有位都设置时,这些位被清除(而不是保留设置最后一个未设置位的位),并且受害者是通过查找第一个未设置位扫描来选择的。这将具有硬件优势,即只需在缓存未命中时读取信息(存储在与 L3 标签不同但附近的不同数组中);缓存命中可以简单地设置适当的位。顺便说一句,这种类型的 NRU 避免了真正 LRU 的一些坏特性(例如,LRU 在某些情况下会降级为 FIFO,在某些情况下,甚至随机替换也可以提高命中率)。

    【讨论】:

      【解决方案3】:

      对于 Intel CPU,更换政策通常没有记录。我做了一些实验来揭示最近 Intel CPU 中的策略,其结果可以在https://uops.info/cache.html 上找到。我使用的代码在GitHub 上可用。

      以下是我的发现总结。

      • Tree-PLRU: 我测试过的所有 CPU 的 L1 数据缓存以及 Nehalem、Westmere、Sandy Bridge、Ivy Bridge、Haswell 和 Broadwell CPU 的 L2 缓存都使用此策略.
      • Randomized Tree-PLRU:一些 Core 2 Duo CPU 在其 L2 缓存中使用 Tree-PLRU 的变体,其中树中的最低位或最高位被(伪)随机性替换。
      • MRU:此政策有时也称为 NRU。每个缓存块使用一位。对块的访问将该位设置为 0。如果最后一位设置为 0,则所有其他位都设置为 1。如果未命中,则替换其位设置为 1 的第一个块。此策略用于 Nehalem、Westmere 和 Sandy Bridge CPU 的 L3 缓存。
      • Quad-Age LRU (QLRU):这是对每个缓存块使用两位的 MRU 策略的概括。此策略的不同变体用于 L3 缓存(从 Ivy Bridge 开始)和 L2 缓存(从 Skylake 开始)。
      • 自适应策略: Ivy Bridge、Haswell 和 Broadwell CPU 可以在两种不同的 QLRU 变体之间动态选择。这是通过 set Dueling 实现的:少数专用集始终使用相同的 QLRU 变体;其余的集合是“追随者集合”,它们使用在专用集合上表现更好的变体。另见http://blog.stuffedcow.net/2013/01/ivb-cache-replacement/

      【讨论】:

        猜你喜欢
        • 2011-01-13
        • 2017-12-20
        • 2016-10-19
        • 1970-01-01
        • 2013-12-27
        • 2019-04-01
        • 2020-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多