【问题标题】:Find hit/miss in cache c++在缓存 C++ 中查找命中/未命中
【发布时间】:2014-04-17 04:45:33
【问题描述】:

我正在努力解决我的硬件问题。它要求读取一个跟踪文件,其中每一行都有引用类型和十六进制地址。例如,文件中的第一行地址为 0x4ef1200231,指令类型。它还要求检查缓存中的这个地址是命中还是未命中(在 L1 和 L2 中)。我不太确定如何编写 c++(我很新)来检查它是成功还是失败。

我正在想象有一个函数,比如地址(long int),然后如果我调用地址(0x4ef1200231),那么控制台可以告诉我这个地址在 L1 是命中还是未命中,以及是否未命中,然后调用另一个函数来检查 L2 的这个地址。这是不是太天真了?请帮忙。谢谢。

---跟踪中的几行---
4ef1200231 整数
2ff1e0122234 写
82039ef9a3 R

注释:Int 表示指令,WR 表示数据写入,R 表示数据读取。问题是在阅读了整个跟踪文件之后,总共有多少次命中和未命中。谢谢。

【问题讨论】:

  • C++ 中没有任何东西可以为您解答这个问题。听起来这可能是一个纸和铅笔的问题。你能编辑你的帖子并添加几行跟踪文件吗?

标签: c++ performance caching memory


【解决方案1】:

这个问题对于 C++ 初学者来说可能太高级了,但这里有一些关于如何实现解决方案的解释......

首先,您需要有一个容器来模仿每一级缓存所使用的逻辑:最简单(并且可能足够)的容器是最近最少使用 (LRU) 数据结构。这样做是记录一个固定的最大数量的缓存中元素,当一个元素被访问时,它会在列表中搜索它:如果找到它,它会被移动到列表的顶部/前面,替换第一个和后续的列表元素直到它留下的空隙再次被填满。如果它不在列表中,那么它也会添加到顶部,所有其他元素向下移动以腾出空间,如果列表达到最大大小,则删除最后一个元素。为了很好地实现 LRU,您需要能够通过值快速查找元素,同时在列表中快速插入和删除元素。最好将unordered_maplist 结合使用,但仅此一项的实现就超出了作为C++ 初学者的合理预期。您可以从仅使用列表开始 - 搜索会很慢(O(n) 或线性/蛮力),但您可以使其正常工作。

给定这样一个 LRU 类,您可以设置两个实例的大小来表示 L1 和 L2 缓存中的页面,然后对于输入文件中的每个地址,您查找该页面(例如,对于 4k 页面,您可以将其除以 4096 , 或按位 - 并且它与 4095 的按位否定,或按位 - 或它与 4095,或将其右移 12 次等)在 L1 中,必要时回退到 L2。 “它是否已经在缓存中”代码可以保持命中/未命中计数器。

这里有一些示例代码可以帮助您入门:

template <typename T>
class Dumb_LRU
{
    Dumb_LRU(size_t max_size) : n_(max_size) { }
    bool operator()(const T& t)
    {
        std::list<T>::iterator i = std::find(l_.begin(), l_.end(), t);
        if (i == l_.end())
        {
            l_.push_front(t);
            if (l_.size() > n_)
                l_.pop_back();
            return false;
        }
        if (i != l_.begin()) // not already the first element...
        {
            l_.erase(i);
            l_.push_front(t);
        }
        return true;
    }
  private:
    std::list<T> l_;
    size_t n_;
};

然后您可以像这样进行模拟:

static const size_t l1_cache_pages = 256;
static const size_t l2_cache_pages = 2048;
static const size_t page_size = 4096;

Dumb_LRU<size_t> l1(l1_cache_pages);
Dumb_LRU<size_t> l2(l2_cache_pages);

size_t address;
std::string doing_what;
int l1_hits = 0, l1_misses = 0, l2_hits = 0, l2_misses = 0;
while (std::cin >> address >> doing_what)
{
    if (l1(address / page_size))
        ++l1_hits;
    else
    {
        ++l1_misses;
        if (l2(address / page_size))
            ++l2_hits;
        else
            ++l2_misses;
}
// ...print out hits/misses...

【讨论】:

  • 非常感谢托尼,这对我来说很有意义。还有一个问题,这可能很愚蠢,但我找不到一个好的答案。如何创建这个容器?我创建了一个列表,然后如何将缓存上的所有地址复制到 L1 和 L2?再次感谢。
  • @user39846:我可能给了你太多帮助,但用代码解释起来更容易......
猜你喜欢
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 2018-09-02
  • 2012-05-13
  • 2021-01-12
  • 2014-02-24
相关资源
最近更新 更多