2013-05-09 66 views
1

我寫了兩個簡單的循環。Parrallel.For循環執行速度比

一種是使用 '的' 標準:

Stopwatch sw = Stopwatch.StartNew(); 

      for (int i = 0; i < 1000000; i++) 
      { 
       Console.WriteLine(i); 
      } 
      sw.Stop(); 
      Console.WriteLine(sw.Elapsed); 
      Console.ReadKey(); 

其次是使用Parrallel.For,其假設是速度快:

sw.Restart(); 
      Parallel.For(0,1000000,i => 
        { 
         Console.WriteLine(i); 
        });    

      sw.Stop(); 
      Console.WriteLine(sw.Elapsed); 

不幸的是,它需要約53秒鐘的第一執行,大約1分50秒到第二個(!!!)。

這是爲什麼,我做錯了什麼?

+4

因爲線程必須同步才能寫入控制檯?嘗試做一些實際的工作。 – GSerg 2013-05-09 08:54:22

+0

起初,有一個數據庫寫入,而不是寫入控制檯,它仍然執行較慢。 – ohadinho 2013-05-09 08:57:13

+3

那麼,db也是使鎖/同步發生的共享資源。爲了獲得性能優勢,您應該儘量避免在並行代碼中使用這些資源。 – GSerg 2013-05-09 09:00:57

回答

0

我想你的代碼中linqpad我用使用的Parallel.For

的for語句和12.5秒9秒,當您嘗試訪問I/O資源,如數據庫,或者你有一個控制檯輸出使用鎖定機制同步您的線程。無論如何,我不建議並行訪問數據庫插入或選擇語句。

不過試試你的代碼這一變化:

Stopwatch sw = Stopwatch.StartNew(); 
StringBuilder str = new StringBuilder(); 

for (int i = 0; i < 1000000; i++) 
{ 
     str.AppendLine(i.ToString()); 
} 

sw.Stop(); 
Console.WriteLine(sw.Elapsed); 

str = new StringBuilder(); 
sw.Restart(); 

Parallel.For(0,1000000,i => 
       { 
        str.AppendLine(i.ToString()); 
       });    

sw.Stop(); 
Console.WriteLine(sw.Elapsed); 

這將下降的時候幾個毫秒幾百。

4

Parallel.For不應該讓循環更快。它應該使其迭代並行執行

在您的嘗試中,您使用的代碼使用的資源無法匹配通過並行循環提供的任何速度提升(可能是因爲它們需要同步,可能是因爲沒有足夠的帶寬等)。因此,你只是爲了跟不上他們的資源而進行線程競賽。你的場景根本不要求並行性(至少不是你嘗試的方式)。

如果您想了解Parallel.For如何提高循環的性能,請考慮在循環內部進行一些計算,將結果保存爲數組中的獨佔(每次迭代)索引,並確保這些計算不要以任何方式依賴於其他迭代的結果。

1

通過並行編程,您可以同時完成更多工作。它會導致您的代碼並行執行。當你第一次看並行編程時,你希望你的速度增加線性。像4個內核一樣快4倍。

但是,只有當您具有最理想的並行編程代碼時纔會發生這種情況。很少有這樣的算法。

代碼的總體加速受限於無法並行化的代碼部分。就像之前在評論和回答中所述,對於Console.WriteLine或Database acces,你的線程必須同步。所以這部分不能並行化。如果您的代碼中有很大一部分不能並行執行,那麼代碼甚至可能比正常循環執行得慢。 (用於同步線程的時間)。

Amdhal的法則給了我們這個結論。

它說,它不能並行將限制整體加速從並行

閱讀更多關於Amdhal定律這裏的計劃的一小部分:

http://en.wikipedia.org/wiki/Parallel_computing