2017-08-01 47 views
1

我有一个带有两个参数的成员函数。两者都是指向复杂对象的指针。当被调用时,该函数执行一些不重要的计算,然后返回一个整数。就像这样:基于呼叫位置的记忆

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的不同实例应具有不同的缓存。

+0

“__FILE__”和“__LINE__”宏如何?第一行会非常简单易用。要添加文件信息,您需要执行大量编译时间魔术来从中生成缓存提示,但这是可能的。 – OutOfBound

+0

你有不同的呼叫站点共享参数,并希望他们从彼此的记忆中受益,还是足以在每个不同的呼叫站点缓存结果? – Useless

+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__) 
+0

使用GCC,你甚至可以执行'int foo(blah,int line = __builtin_LINE())'来避免显式的'__LINE__'。但OP没有说他们只用它在一个单一的文件。 – HolyBlackCat

+0

@HolyBlackCat是的,我知道,使用这条线是不安全的,这就是为什么线缓存里面有一个secon映射。内置函数的想法非常好。我不知道这件事。 – OutOfBound

0

_ReturnAddress或任何替代为你的编译器。也许你可以在你的项目中使用它。显然,如果它适合你,不仅仅是创建map调用者结果。