C++简单的缓存设计用于函数输出

C++ simple cache design for function output

本文关键字:用于 函数 输出 简单 缓存 C++      更新时间:2023-10-16

我认为这是众所周知的解决方案中一个非常常见的问题,但我并没有能够找到。所以我在这里寻求建议。

问题陈述

考虑以下设置:

class A; // some class
const A f(const A&); // an _expensive_ function
void do_stuff()
{
    A a;
    a.modify(...);
    do_stuff1(f(a));  // compute f(a)
    do_stuff2(f(a));  // use cached value of f(a)
    a.modify(...);
    do_stuff3(f(a));  // recompute f(a)
}

我希望f(a)的返回值缓存在第一个和但是在对a.modify()的第二次调用之后被丢弃。EDIT:在实践中,对f(a)的调用将在不同的作用域中。

以下是我探索过的一些解决方案,值得一提。

解决方案1:中央缓存

使用时间戳

我可以想象一个简单的解决方案,包括向类A添加一个时间戳函数CCD_ 5可以检查并决定是否需要更新其缓存的结果,存储在中央缓存中的某个位置。我想这也意味着要改变f至的签名

const A& f(const A&);

问题1:对于中央缓存,我们需要一种机制来销毁当CCD_ 8被破坏时CCD_。

使用哈希码

除了问题1,这似乎很简单。但当A代表CCD_ 10。我想应该排除动态多态性在这里所以我们忘记了为std::vector<...>的子类添加时间戳这意味着压倒一切。然而,我们可以计算一些散列码或UUID基于a的内容——假设它比计算便宜得多f(a)-并将中央缓存建立在这些散列码的基础上。但我们面临问题1再次出现。

解决方案2:耦合对象

我还没有找到如何实现这一点,但想法是让a通知当a被写入或销毁时,f(a)的缓存,但当只是从中读取。如果没有动态多态性,我想不出如何做到这一点,并且在不减慢使用CCD_ 17或迭代器,为每个修改的元素向缓存发送通知。

问题2:找到一种将更改集定界为a的机制,以便对每组更改仅使缓存无效一次。

我想到了在a上启用写访问的代理(灵感来自这个概念互斥体(,但无法想出任何工作代码。

有什么想法吗?

我用这样的接口做过类似的事情:

class F
{
public:
 virtual int f(int a)=0;
};
class Cache : public F
{
public:
   Cache(F &f) : f(f) { }
   int f(int a) { /*caching logic here, calls f.f() if not found from cache */ }
   F &f;
};
class Impl : public F
{
   int f(int a) { /* real implementation here */ }
};

然后它只是决定在哪里使用缓存逻辑:

   Impl i; 
   Cache c(i);
   c.f(10); // put to cache with key 10
   c.f(10); // found from cache
   c.f(11); // put to cache with key 11

你就不能这么做吗:

const A &cacheA = f(a);
do_stuff1(cacheA);  // compute f(a)
do_stuff2(cacheA);  // use cached value of f(a)

我可能遗漏了一些重要的细节,但您不能仅为此目的使用LRU缓存吗?

让f成为a的成员。然后,您可以在a的实例中决定是否可以重用缓存的结果。