2010-02-06 53 views
1

我剖析C#應用程序,它看起來像每個呼叫Dictionary<>.ContainsKey() 5000時間每兩個線程兩個獨立但相同的字典(只有兩個項目)作爲慢作爲一個線程在一個字典調用Dictionary<>.ContainsKey() 10000次的兩倍。多線程減慢整體字典訪問速度?

我使用名爲JetBrains dotTrace的工具測量「線程時間」。我明確使用相同數據的副本,因此沒有我正在使用的synhronization基元。 .NET有可能在幕後進行一些同步嗎?

我有一個雙核心機器,並且有三個線程正在運行:一個使用Semaphore.WaitAll()被阻止,而工作是在兩個新線程上完成的,其優先級設置爲ThreadPriority.Highest

明顯的罪魁禍首喜歡,沒有實際並行運行代碼,而不是使用一個發佈版本已被排除。

編輯:

人們想要的代碼。好吧:

private int ReduceArrayIteration(VM vm, HeronValue[] input, int begin, int cnt) 
    { 
     if (cnt <= 1) 
      return cnt; 

     int cur = begin; 

     for (int i=0; i < cnt - 1; i += 2) 
     { 
      // The next two calls are effectively dominated by a call 
      // to dictionary ContainsKey 
      vm.SetVar(a, input[begin + i]); 
      vm.SetVar(b, input[begin + i + 1]); 
      input[cur++] = vm.Eval(expr); 
     } 

     if (cnt % 2 == 1) 
     { 
      input[cur++] = input[begin + cnt - 1]; 
     } 

     int r = cur - begin; 
     Debug.Assert(r >= 1); 
     Debug.Assert(r < cnt); 
     return r; 
    } 

    // From VM 
    public void SetVar(string s, HeronValue o) 
    { 
     Debug.Assert(o != null); 
     frames.Peek().SetVar(s, o); 
    } 

    // From Frame 
    public bool SetVar(string s, HeronValue o) 
    { 
     for (int i = scopes.Count; i > 0; --i) 
     { 
      // Scope is a derived class of Dictionary 
      Scope tbl = scopes[i - 1]; 
      if (tbl.HasName(s)) 
      { 
       tbl[s] = o; 
       return false; 
      } 
     } 
     return false; 
    } 

現在這裏是線程產卵的代碼,這可能會被延遲:

public static class WorkSplitter 
{ 
    static WaitHandle[] signals; 

    public static void ThreadStarter(Object o) 
    { 
     Task task = o as Task; 
     task.Run(); 
    } 

    public static void SplitWork(List<Task> tasks) 
    { 
     signals = new WaitHandle[tasks.Count]; 
     for (int i = 0; i < tasks.Count; ++i) 
      signals[i] = tasks[i].done; 
     for (int i = 0; i < tasks.Count; ++i) 
     { 
      Thread t = new Thread(ThreadStarter); 
      t.Priority = ThreadPriority.Highest; 
      t.Start(tasks[i]); 
     } 
     Semaphore.WaitAll(signals); 
    }   
} 
+0

你能解釋一下也許你正在試圖用這些線程和字典... – 2010-02-06 04:07:19

+0

編寫解釋來解決實際的問題,我需要一定的並行矢量運算。 – cdiggins 2010-02-06 04:15:59

+0

你應該發佈你的代碼。 – ChaosPandion 2010-02-06 04:19:46

回答

4

即使有在詞典(沒有)任何鎖定,它不能影響你的因爲每個線程正在使用一個單獨的測量。運行這個測試10,000次不足以獲得可靠的時序數據,ContainsKey()只需要20納秒左右。您至少需要幾百萬次才能避免計劃工件。

+0

問題是我需要這個在10,000次迭代中快速。獲取更多迭代的時間安排,將會針對我不關心的情況進行優化。我只是有一段時間試圖充分利用第二個核心進行操作,我知道理論上應該是可並行化的。 – cdiggins 2010-02-06 04:32:35

+2

當線程僅執行200微秒時,我看不出如何預期並行操作。你必須很幸運才能同時啓動兩個線程。 – 2010-02-06 04:45:24

+0

線程的運行時間比這更長,整個測試需要大約100毫秒的時間才能在沒有儀器的情況下運行。我的配置文件說,第二個最熱門的熱點是Dictionary中的「FindEntry」。它說在測試中用一個線程在這裏花費了296毫秒,而在兩線程中測試了577毫秒。這在數十次試驗中都是非常一致的,並且讓我大跌眼鏡。 – cdiggins 2010-02-06 04:56:30