【问题标题】:Simplescalar cache LRU implementation简单标量缓存 LRU 实现
【发布时间】:2012-03-15 22:06:15
【问题描述】:

我在 cache.c 文件中寻找 LRU 代码,但这是我能找到的唯一代码:

switch (cp->policy) {

  case LRU:

  case FIFO:

    repl = cp->sets[set].way_tail;
    update_way_list(&cp->sets[set], repl, Head);
    break;

在我看来好像缺少 LRU 代码,我认为应该将 LRU 算法放在冒号之后。所以如果我错过了什么,你能给我指出正确的方向或给我一些提示吗?

非常感谢。

【问题讨论】:

  • 我了解情况:您正在阅读一些代码,但其中一些似乎丢失了。但我不明白问题是什么。为什么不问问代码的作者呢?

标签: c caching lru


【解决方案1】:

不看其余代码很难说,但我在这里看到了两种明显的可能性。一个是,正如您所建议的,LRU 管理的代码丢失了,可能是由于编辑错误。

然而,我认为更有可能的是,对于代码的这个特定部分,LRU 和 FIFO 管理做同样的事情,所以它们取决于 C 语句的“失败”在这种情况下为两者执行相同的代码(但可能会为其他策略执行其他代码)。

【讨论】:

  • 这更像是第二种情况,我应该检查其余的代码。非常感谢。
  • 有一个约定(我认为一个很好的约定)在空的case 标签之后放置一个/* fall-through */ 评论(在这个例子中是LRU);它的意图很明确,即作者没有忘记break 声明。
【解决方案2】:

我之前碰巧使用过 Simplescalar。其实Simplescalar已经实现了真正的LRU算法。

以下注释清楚地描述了函数 update_way_list。

/* insert BLK into the order way chain in SET at location WHERE */
static void
update_way_list(struct cache_set_t *set,        /* set contained way chain */
                struct cache_blk_t *blk,        /* block to insert */
                enum list_loc_t where)          /* insert location */

您引用的代码来自访问缓存时的“缓存未命中”案例:

  switch (cp->policy) {
  case LRU:
  case FIFO:
    repl = cp->sets[set].way_tail;
    update_way_list(&cp->sets[set], repl, Head);
    break;
  }

这里选择集合的最后一条路径作为牺牲品,并将其移动到集合的头部。 稍后,被替换的块数据被写回,然后受害者被新的数据块替换。

区分LRU和FIFO最重要的部分来自“缓存命中”的情况:

  /* if LRU replacement and this is not the first element of list, reorder */
  if (blk->way_prev && cp->policy == LRU)
    {
      /* move this block to head of the way (MRU) list */
      update_way_list(&cp->sets[set], blk, Head);
    }

因此,集合中的方式遵循年龄递减顺序:集合的头部是 MRU(最近使用)块,尾部是 LRU。

这正是真正的 LRU 算法:当有缓存命中时,命中块被提升为 MRU 方式,同时保持其他的顺序。当缓存未命中时,LRU 块被选为牺牲品,新块被放置在 MRU 方式中。如果我们删除之前的“缓存命中”代码,则不会记录访问历史记录,并且集合中的方式遵循访问顺序,从而提供 FIFO 行为。如果我们删除该行

    update_way_list(&cp->sets[set], repl, Head);

在前面的“cache miss”代码中,那么新的block会以LRU方式放置,从而提供LIP(LRU Insertion Policy)行为。

【讨论】:

    【解决方案3】:

    看起来代码的其他部分以 FIFO 或 LRU 顺序对 cp->sets 中的条目进行排序,以便无论替换策略是什么,要替换的集合始终是 cp->sets[set].way_tail。这两种替换策略仅在使用或添加线路时有所不同,在线路被替换时没有区别。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-05
      • 2010-11-03
      • 2015-07-19
      • 2015-02-13
      • 1970-01-01
      • 2011-09-17
      • 2023-03-26
      相关资源
      最近更新 更多