2013-05-16 34 views
3

我正在編寫一個計算量很大的應用程序(NLP機器學習任務),它需要優化。優化Dictionary.TryGetValue()

由於我的代碼有很多for循環,我使用Parallel.For(和變體)來並行化最外層的循環。 我也使用數組和Dictionary s來構建幾個指標,大大降低成本。

VS2010的分析器顯示應用程序花費大部分時間在Dictionary.TryGetValue()(這是索引的副產品)。

這引出了我能否做得更好的問題?如何?

我的第一個問題是,在我的場景中是否存在普遍的共識ConcurrentDictionary.TryGetValueDictionary.TryGetValue好 - 很多讀者,沒有作家?

我沒有動力去編寫我自己的hashmap,因爲它可能比.NET的集合更糟糕。但是有沒有哪些庫可以保證我的場景更快速的查找?

也許哈希碼實現放緩了事情?

回答

9

Dictionary.TryGetValue已經非常良好優化,根據MSDN:

此方法接近的O(1)的操作。

您還沒有提到什麼是你的字典的鍵,如果你使用了自定義類型,請確保您已經實現了GetHashCode方法不當,如字典和哈希表依靠它並廣泛使用它。

+2

'O(1)'與「非常優化」並不完全相同。我可以將'Thread.Sleep(60000)'添加到方法的開頭,並且仍然合法地聲稱它是'O(1)'; p –

+3

是的,您可以,但如果您在最大性能之後,則不會;)我的意思是,** TryGetValue **方法不太可能導致速度下降,但如果編碼不正確,** GetHashCode **方法可能會這樣做。 –

+0

我已經介紹了GetHashCode方法,並且程序花費的時間少於0.1%。我想我需要用不同的方式來解決這個瓶頸問題。 – Howie

4

我的第一個問題是,是否存在ConcurrentDictionary.TryGetValue在我的情況下執行任何優於Dictionary.TryGetValue普遍的共識 - 許多讀者,沒有作家呢?

我沒有測試過,但我通常會期望併發執行具有額外的開銷,稍微慢整體。當您需要同步訪問時會有所不同 - 即如果您的以讀取爲中心的代碼需要lock字典,則併發版本(無鎖)可能會更快。既然你提到你的代碼沒有編寫者,我猜你沒有使用locks,因此沒有任何理由去看另一個實現。這就是說,它可能是值得剖析它,但即使更快(又:我希望它是稍微),我只希望它是快 - 所以不太可能顯着改變性能。

0

當其要求的方法是負責大部分的執行時間探查結果來看,同樣重要的是要弄清楚如果是因爲:

  1. 該方法被調用次數過多,或
  2. 方法的一次調用需要很長的時間

如果TryGetValue,因爲它被稱爲太多次佔了大部分時間,它可能是你需要減少complexit指示您的索引/查找算法的y,以便TryGetValue可以不頻繁調用。

如果每個調用花費很長時間,它將只值得進一步調查TryGetValue方法。然而,正如Pavel提到的,TryGetValue本身已經很好的優化了。這很可能是TryGetValue所調用的方法,可以被你覆蓋的方法將被指責。通常您需要注意GetHashCodeEquals方法。撥打TryGetValue時,他們都會被調用。 Equals可能會被調用多次。我的經驗是Equals方法通常有更好的機會成爲問題,因爲某些框架構造的內置等式比較涉及反射。