[英]C++ simple cache design for function output
我认为这是众所周知的解决方案的一个非常常见的问题,我无法找到。 所以我在这里寻求建议。
考虑以下设置:
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()
后被丢弃。 编辑:实际上,对f(a)
的调用将在不同的范围内。
以下是我探索过的一些解决方案,它们的价值。
我可以想象一个简单的解决方案,涉及向 class A
添加时间戳,function f
可以检查并决定是否需要更新其缓存结果,存储在中央缓存的某个位置。 我想这也意味着将f
的签名更改为:
const A& f(const A&);
问题 1:使用中央缓存,我们需要一种机制来在a
被销毁时销毁f(a)
的缓存结果。
除了问题 1,这似乎很简单。 但是当A
代表std::vector<...>
时,它会变得复杂。 我想这里应该排除动态多态性。 所以我们忘记了向std::vector<...>
的子类添加时间戳以及它所暗示的所有覆盖。 但是,我们可以根据a
的内容计算一些 hash 代码或 UUID --- 假设它比计算f(a)
便宜得多 --- 并将中央缓存基于这些 hash 代码。 但我们再次面临问题 1。
我还没有找到如何实现这一点,但想法是在写入或销毁a
时通知f(a)
a
缓存,而不是在仅读取它时通知缓存。 如果没有动态多态性,并且不使用operator[]
或迭代器通过将通知发送到每个已修改元素的缓存来减慢单元素访问速度,我无法弄清楚如何做到这一点。
问题 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 缓存吗?
使 fa 成为 A 的成员。然后您可以在 A 的实例中决定是否可以重用缓存的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.