在缓存c ++中查找命中/未命中

时间:2014-04-17 04:45:34

标签: c++ performance caching memory

我和我的hw挣扎。它要求读取一个跟踪文件,其中每一行都有引用类型,并且地址为十六进制。例如,文件中的第一行具有地址0x4ef1200231,具有指令类型。它还要求检查缓存中的该地址是命中还是未命中(在L1和L2中)。我不太确定如何编写c ++(我是非常新的)来检查它是否是命中或未命中。

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

---痕迹中的几行---
4ef1200231 Int
2ff1e0122234 WR
82039ef9a3 R

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

1 个答案:

答案 0 :(得分:2)

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

首先,您需要一个容器来模仿每个级别的缓存所使用的逻辑:最简单(也可能是足够的)这样的容器是最近最少使用(LRU)数据结构。这样做是记录一个固定的最大数量的缓存内元素,当一个元素被访问时,它在列表中搜索它:如果它被发现它被移动到列表的顶部/前面,取代第一个和后面的列表元素直到它留下的空隙再次被填满。如果它不在列表中,那么它也会添加到顶部,所有其他元素向下移动以腾出空间,如果列表处于最大大小,则删除最后一个元素。要很好地实现LRU,您需要能够按值快速查找元素,同时在列表中快速插入和删除元素。最好使用unordered_maplist的组合,但单独实现这一点比你可以合理地期望作为C ++初学者做的更多。你可以从只使用一个列表开始 - 搜索速度很慢(O(n)或线性/强力),但你可以让它在功能上运行。

给定这样一个LRU类,你可以设置两个实例的大小来表示L1和L2缓存中的页面,然后对于输入文件中的每个地址,你寻找那个页面(比如4k页,你可以将它除以4096 ,或按位 - 并且它与4095的按位否定,或者按位 - 或者它与4095,或者在12中将其右移12次等),如果必要则回落到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...