对于只有两种路的传统缓存,每组一个位可用于跟踪 LRU。在对命中的集合进行任何访问时,可以将该位设置为未命中的方式。
对于更大的关联性,状态的数量急剧增加:路数的阶乘。因此,4 路缓存将有 24 个状态,每组需要 5 位,而 8 路缓存将有 40,320 个状态,每组需要 16 位。除了存储开销之外,更新值的开销也更大。
对于 4 路缓存,以下状态编码似乎工作得相当好:两位表示最近使用的路号,两位表示下一个最近使用的路号,以及一位指示是否较高或最近使用的编号较低的方式。
- 当 MRU 命中时,状态不会改变。
- 在下一个 MRU 命中时,两个位字段将被交换。
- 在其他命中时,对另外两个路的编号进行解码,命中的路的编号被放置在第一个两位部分中,并且前一个MRU路编号被放置在第二个两位部分中。最后一位的设置取决于下一个 MRU 路号是否高于或低于最近较少使用的路号not hit.
- 如果未命中,状态会更新,就像发生了 LRU 命中一样。
由于 LRU 跟踪具有如此大的开销,因此通常使用二叉树伪 LRU 等更简单的机制。在命中时,这样只会更新树的每个分支部分,命中的相关路的一半。对于路数 W 的幂,二叉树 pLRU 缓存每组将具有 W-1 位状态。 8 路高速缓存的路 6 中的命中(使用 3 级二叉树)将清除树底部的位,以指示下半路 (0,1,2,3) 较少最近使用过,清除下一级的较高位以指示这些方式 (4,5) 的下半部分最近较少使用,并设置最终级别的较高位以指示这些方式的上半部分 (7)最近使用较少。不必读取此状态来更新它可以简化硬件。
对于倾斜关联性,不同的方式使用不同的散列函数,已经提出了类似缩写时间戳的东西(例如,“倾斜关联缓存的分析和替换”,Mark Brehob 等人,1997)。使用未命中计数器比循环计数更合适,但基本思想是相同的。
对于两个核心尝试同时写入同一缓存行时发生的情况,这是通过在给定时间仅允许一个 L1 缓存使缓存行处于独占状态来处理的。实际上,存在一场竞赛,一个核心将获得独占访问权。如果只有一个写入核心已经拥有缓存行shared州,它可能更有可能赢得比赛。当缓存行处于共享状态时,缓存只需向该缓存行的其他潜在持有者发送失效请求即可;如果缓存行不存在,则写入通常需要请求缓存行数据以及请求独占状态。
不同内核对同一高速缓存行的写入(无论是相同的特定地址,还是在错误共享的情况下,写入数据行内的另一个地址)可能会导致“高速缓存行乒乓球”,其中不同的内核使高速缓存无效其他缓存中的行以获得独占访问(执行写入),以便缓存行像乒乓球一样在系统中弹跳。