簡體   English   中英

C++ 關於 boost::unordered_map & boost::hash 的一些問題

[英]C++ some questions on boost::unordered_map & boost::hash

我最近才開始研究 boost 及其容器,我閱讀了一些關於 web 和 stackoverflow 的文章,其中 boost::unordered_map 是大型 collections 中性能最快的容器。 所以,我有這個 class State,它在容器中必須是唯一的(沒有重復),容器中將有數百萬甚至數十億的狀態。 因此,我一直在嘗試將其優化為小尺寸和盡可能少的計算。 我之前使用過 boost::ptr_vector,但正如我在 stackoverflow 上所讀到的,只要其中沒有那么多對象,向量才是好的。 在我的例子中,State 描述了來自機器人的感覺運動信息,因此可能存在大量狀態,因此快速查找是重中之重。 按照 unordered_map 的boost 文檔,我意識到我可以做兩件事來加快速度:使用 hash_function,並使用相等運算符根據它們的 hash_function 比較狀態。 因此,我實現了一個私有 hash() function,它接收 State 信息並使用 boost::hash_combine,創建一個 std::size_t Z0800FC577294C34E0B258AD2839Z43 值。 operator== 基本上比較狀態的 hash 值。 所以:

  • std::size_t 是否足以涵蓋數十億可能的 hash_function 組合? 為了避免重復狀態,我打算使用它們的 hash_values。

  • 創建 state_map 時,我應該使用 State* 還是 hash 值作為鍵? 即: boost::unordered_map<State*,std::size_t> state_map; boost::unordered_map<std::size_t,State*> state_map;

  • 使用 boost::unordered_map::iterator = state_map.find() 的查找時間是否比通過 boost::ptr_vector 並比較每個迭代器的鍵值更快?

  • 最后,任何關於如何優化這種無序 map 以實現速度和快速查找的提示或技巧將不勝感激。

編輯:我已經看到了很多答案,一個是不使用 boost 但 C++0X,另一個不使用 unordered_set,但老實說,我仍然想看看 boost::unordered_set 如何與 hash function 一起使用. 我遵循了boost的文檔並實施了,但我仍然不知道如何使用有序集的boost hash function。

這有點糊塗了。

  • 你所說的不是“你可以做些什么來加快速度”; 相反,它們是您的類型的強制性要求,才有資格作為無序 map 的元素類型,也適用於無序集(您可能更想要)。

  • 您需要提供一個比較對象的相等運算符,而不是 hash 值。 相等的全部意義在於區分具有相同 hash 的元素。

  • size_t是無符號整數類型,在 x86 上為 32 位,在 x64 上為 64 位。 由於您想要“數十億個元素”,這意味着許多 GB 的數據,我假設您無論如何都有一台可靠的 x64 機器。

  • 關鍵是您的 hash function 是好的,即很少發生碰撞。

  • 你想要一套,而不是 map。 將對象直接放入集合中: std::unordered_set<State> 如果您要映射某物,即狀態到其他某物,請使用 map。 哦,如果可以的話,使用 C++0x,而不是 boost。

  • 使用hash_combine很好。


寶貝示例:

struct State
{
  inline bool operator==(const State &) const;
  /* Stuff */
};

namespace std
{
  template <> struct hash<State>
  {
    inline std::size_t operator()(const State & s) const
    {
      /* your hash algorithm here */
    }
  };
}

std::size_t Foo(const State & s) { /* some code */ }

int main()
{
  std::unordered_set<State> states; // no extra data needed
  std::unordered_set<State, Foo> states; // another hash function
}

unordered_map 是一個哈希表。 您不存儲 hash; 它作為存儲和查找方法在內部完成。

鑒於您的要求,unordered_set 可能更合適,因為您的 object 是唯一要存儲的項目。

不過,您有點困惑——相等運算符和 hash function 並不是真正的性能項目,而是容器正常工作的重要對象所必需的。 A good hash function will distribute your nodes evenly across the buckets, and the equality operator will be used to remove any ambiguity about matches based on the hash function.

std::size_t 適用於 hash function。 請記住,沒有 hash 是完美的; 會有碰撞,這些碰撞項存儲在該桶 position 的鏈表中。

因此,.find() 在最佳情況下為 O(1),在平均情況下非常接近 O(1)(而在最壞情況下為 O(N),但一個不錯的 hash function 將避免這種情況。)

您沒有提及您的平台或架構; 在數十億個條目中,您可能仍然需要擔心內存不足的情況,具體取決於這些情況以及 State object 的大小。

忘記 hash; 沒有任何東西(至少從你的問題來看)表明你有一個有意義的鑰匙;

讓我們退后一步,重新表述您的實際績效目標:

  • 您想快速驗證任何 State 對象不存在重復項

如果我需要添加其他人,請發表評論。

從上述目標和您的評論來看,我建議您實際上使用ordered_set而不是unordered_map。 是的,有序搜索使用二進制搜索 O(log (n)),而無序使用查找 O(1)。

但是,不同之處在於,使用這種方法,您需要ordered_set 來檢查類似的 state在您即將創建一個新的時是否已經存在,即在 State創建時間

所有其他查找中,您實際上不需要查看ordered_set; 因為您已經擁有密鑰 State*: 並且密鑰可以通過魔術解引用運算符訪問值: *key

因此,使用這種方法,您僅使用ordered_set 作為索引來僅在創建時間驗證狀態。 在所有其他情況下,您可以使用指針值鍵的取消引用運算符訪問您的 State。

如果以上所有內容都不足以說服您,這里是使用 hash 快速確定相等性的想法的最后釘子; hash function 發生碰撞的概率很小,但是隨着狀態數量的增加,該概率將變得完全確定。 因此,根據您的容錯能力,您將處理 state 碰撞(從您的問題和您期望處理的狀態數量來看,您似乎會處理很多)

為此,您顯然需要比較謂詞來測試 state 的所有內部屬性(陀螺儀、推進器、加速度計、質子射線等)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM