2012-12-30 60 views
0

如何在谷歌稀疏哈希映射中使用低噪聲哈希函數? 你能否給我一步一步的指導如何使用雜音哈希函數? 我正在使用visual C++。谷歌稀疏哈希與雜音哈希函數

目前我在谷歌稀疏哈希映射中使用std :: hash哈希函數。 使用std :: hash和murmur hash實現的goole sparse hash map是否有任何性能差異?

+0

您可能想在使用MurmurHash3之前閱讀此內容,尤其是在安全可能成爲問題時。 http://emboss.github.io/blog/2012/12/14/breaking-murmur-hash-flooding-dos-reloaded/ – Dave

回答

3

你需要提供散列函數給sparse_hash_map模板。我檢查了https://sites.google.com/site/murmurhash/;它的接口與std::hash<>不同,所以您需要編寫適配器類。這裏有一個工作示例(請記住,適配器只包括某些情況下):

#include <iostream> 
#include <sparsehash/sparse_hash_map> 

using google::sparse_hash_map;  // namespace where class lives by default 
using namespace std; 

// 64-bit hash for 64-bit platforms 
// copied from https://sites.google.com/site/murmurhash/ 
uint64_t MurmurHash64A (const void * key, int len, unsigned int seed) 
{ 
    const uint64_t m = 0xc6a4a7935bd1e995; 
    const int r = 47; 

    uint64_t h = seed^(len * m); 

    const uint64_t * data = (const uint64_t *)key; 
    const uint64_t * end = data + (len/8); 

    while(data != end) 
    { 
    uint64_t k = *data++; 

    k *= m; 
    k ^= k >> r; 
    k *= m; 

    h ^= k; 
    h *= m; 
    } 

    const unsigned char * data2 = (const unsigned char*)data; 

    switch(len & 7) 
    { 
    case 7: h ^= uint64_t(data2[6]) << 48; 
    case 6: h ^= uint64_t(data2[5]) << 40; 
    case 5: h ^= uint64_t(data2[4]) << 32; 
    case 4: h ^= uint64_t(data2[3]) << 24; 
    case 3: h ^= uint64_t(data2[2]) << 16; 
    case 2: h ^= uint64_t(data2[1]) << 8; 
    case 1: h ^= uint64_t(data2[0]); 
      h *= m; 
    }; 

    h ^= h >> r; 
    h *= m; 
    h ^= h >> r; 

    return h; 
} 

// simple hash adapter for types without pointers 
template<typename T> 
struct MurmurHasher { 
    size_t operator()(const T& t) const { 
     return MurmurHash64A(&t, sizeof(t), 0); 
    }  
}; 

// specialization for strings 
template<> 
struct MurmurHasher<string> { 
    size_t operator()(const string& t) const { 
     return MurmurHash64A(t.c_str(), t.size(), 0); 
    }  
}; 

struct eqstr 
{ 
    bool operator()(const char* s1, const char* s2) const 
    { 
    return (s1 == s2) || (s1 && s2 && strcmp(s1, s2) == 0); 
    } 
}; 

int main() 
{ 
    sparse_hash_map<const char*, int, MurmurHasher<const char*>, eqstr> months; 

    months["january"] = 31; 
    months["february"] = 28; 
    months["march"] = 31; 
    months["april"] = 30; 
    months["may"] = 31; 
    months["june"] = 30; 
    months["july"] = 31; 
    months["august"] = 31; 
    months["september"] = 30; 
    months["october"] = 31; 
    months["november"] = 30; 
    months["december"] = 31; 

    cout << "september -> " << months["september"] << endl; 
    cout << "april  -> " << months["april"] << endl; 
    cout << "june  -> " << months["june"] << endl; 
    cout << "november -> " << months["november"] << endl; 

    sparse_hash_map<string, int, MurmurHasher<string>> years; 
    years["2012"] = 366; 
    cout << "2012  -> " << years["2012"] << endl; 
} 

性能可能會取決於你的數據模式,所以你應該自己做測試。

+0

非常感謝。這就是我正在尋找的東西。我會做性能測試。 – user1815763

+0

你的答案拯救了我的一天!謝謝! –

+0

在使用MurmurHash3之前,您可能需要閱讀本文,尤其是在安全可能成爲問題時。 http://emboss.github.io/blog/2012/12/14/breaking-murmur-hash-flooding-dos-reloaded/ [哎呀,這應該是在問題上,而不是答案!我無法移動它,所以我現在正在複製它。道歉rburny! ] – Dave