2017-08-01 75 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調用者結果。