根据呼叫位置进行记忆

时间:2017-08-01 22:08:47

标签: c++ memoization

我有一个带有两个参数的成员函数。两者都是指向复杂对象的指针。调用时,函数执行一些非平凡的计算,然后返回一个整数。像这样:

struct Fooer {
  int foo(const A* a, const B* b);
};

如果foo()被赋予相同的两个参数,则返回的整数始终相同。这个函数使用得非常频繁,所以记住它的结果是有意义的。通常,一些查找表,其中键是指针对就足够了。但是,我处于一个独特的位置,我知道所有的呼叫站点,我知道任何给定的呼叫站点总是在执行期间使用相同的参数对。如果我只能传入第三个​​参数,这可以大大加快记忆速度,这是一个基本上是缓存提示的唯一整数:

struct Fooer {
  int foo(const A* a, const B* b, int pos) {
    if (cached_[pos] > 0) return cached_[pos];
    cached_[pos] = /* Heavy computation. */ + 1;
    return cached_[pos];
  }

  std::vector<int> cached_;
};

我正在寻找的是一种轻松生成此“缓存提示”的机制。但没有想到任何事情。现在,我手动将此参数添加到foo()的调用网站,但它显然是丑陋和脆弱的。这个功能真的被大量使用,所以如果你想知道的话,值得进行这种优化。

更一般地说,我希望在每个调用站点都有某种“thunk”,在第一次调用时执行繁重的操作,然后只返回预先计算的整数。

请注意foo()是一个成员函数,因此Fooer的不同实例应该有不同的缓存。

2 个答案:

答案 0 :(得分:0)

这种方法对你有帮助吗?

struct Fooer {

  using CacheMap = std::map<std::pair<const A*, const B*>, int>;
  std::map<int, CacheMap> lineCache;

  int foo(const A* a, const B* b, int line) {
    const auto key = std::make_pair(a,b);
    if (linecache.count(line) > 0) {
        CacheMap& cacheMap = lineCache[line];
        if(cacheMap.count(key)) return cacheMap[key];
    }
    lineCache[line][key] = /* Heavy computation. */ + 1;
    return cacheMap[key];
  }

};
// Calling
foo(a, b, __LINE__)

答案 1 :(得分:0)

请参阅_ReturnAddress或您的编译器的任何替代方案。也许你可以在你的项目中使用它。显然,如果它对您有用,那么只需创建map caller-result。