2016-01-09 49 views
1

我有以下代碼(從LINQPad在這裏複製)。很明顯,看起來我並不瞭解TPL是如何工作的,或者代碼是垃圾,爲什麼並行版本比非並行版本運行速度慢?爲什麼這個並行代碼比其類似的非並行版本慢?

for (int i = 0; i < 100; i++) 
{ 
    ParallelOptions ops = new ParallelOptions(); 
    ops.MaxDegreeOfParallelism = Environment.ProcessorCount; 

    var watch = Stopwatch.StartNew(); 
    Parallel.ForEach<int>(Enumerable.Range(1, 10000000), ops, x => { int y = x + 1; }); 
    watch.Stop(); 
    Console.WriteLine("Parallel: {0}", watch.Elapsed.TotalSeconds); 

    watch = Stopwatch.StartNew(); 
    foreach (var x in Enumerable.Range(1, 10000000)) 
    { 
     int y = x + 1; 
    } 
    watch.Stop(); 
    Console.WriteLine("Non-parallel: {0}\n", watch.Elapsed.TotalSeconds); 
} 

前10個結果:

並行:0.1991644 非平行:0.0466178

並行:0.1723428 非平行:0.0447134

並行:0.1141791 非平行:0.0444557

平行:0.1758878 非平行:0.0444636

並行:0.1687637 非平行:0.0444338

並行:0.1677679 非平行:0.0445771

並行:0.1191462 非平行:0.0446116

並行: 0.1702483 非平行:0.0454863

並行:0.1143605 非平行EL:0.0451731

並行:0.2155218 非平行:0.0450392

+0

啓動線程也不是沒有成本 –

+0

調試模式編譯?由於優化後的代碼什麼都不做,甚至可能會被優化。在決定哪一個更快的時候沒有意義:什麼也不做,或者什麼都不做。 –

+0

線程非常昂貴;只有當你有大量的工作要做時才僱用員工纔有意義。 –

回答

3

好了,你可以得到最好的答案是運行Profiler工具和測量正在發生的事情與你的代碼。但我的猜測是,你的並行代碼比較慢,因爲你的代碼非常簡單,啓動線程並在它們之間切換增加了很多成本,以至於計算速度的優勢可以忽略不計。

但是嘗試做一些實質性的計算,最終你會獲得並行執行優勢。你的代碼太簡單了。現代CPU不能以這種方式加載。

0

由於我無法將此添加爲評論,我添加了另一個發佈修改後的代碼的答案。 @ixSci在他的回答中說什麼似乎是正確的。我在執行非常快的並行代碼體內執行了一項簡單的操作,但速度很慢,這是因爲在線程之間的上下文切換花了很多時間?當我將代碼更改爲休眠一段時間而不是將int值增加1時,並行代碼大約是4(我的CPU中的核數量)比非並行版本快了幾倍。

for (int i = 0; i < 100; i++) 
{ 
    ParallelOptions ops = new ParallelOptions(); 
    ops.MaxDegreeOfParallelism = Environment.ProcessorCount; 

    var partitioner = Partitioner.Create<int>(Enumerable.Range(1, 5000)); 

    var watch = Stopwatch.StartNew(); 
    Parallel.ForEach<int>(partitioner, ops, x => { Thread.Sleep(1); }); 
    watch.Stop(); 
    Console.WriteLine("Parallel: {0}", watch.Elapsed.TotalSeconds); 

    watch = Stopwatch.StartNew(); 
    foreach (var x in Enumerable.Range(1, 5000)) 
    { 
     Thread.Sleep(1); 
    } 
    watch.Stop(); 
    Console.WriteLine("Non-parallel: {0}\n", watch.Elapsed.TotalSeconds); 
} 

前10個結果:

並行:1.2887589 非平行:5.0020569

並行:1.277047 非平行:5.0011116

並行:1.2790631 非平行:5.0001498

Parallel:1.2770644 Non-pa rallel:5。0052016

並行:1.2770013 非平行:5.0021479

並行:1.2770031 非平行:5.0001927

並行:1.2799937 非平行:5.0062141

並行:1.2819909 非並行:5.0171945

並行:1.2780496 不平行:5.0071667

並行:1.2821714 非平行:5.0082108

並行:1.2777875 非平行:5.0152099

+0

這也不是一個好例子。如果你和'ThreadPool'停止限制使用的線程數量(不要強制'MaxDegreeOfParallelism'爲'ProcessorCount'並且增加像ThreadPool.SetMinThreads(100,4);'),那麼你將會得到的加速比CPU內核的數量要多得多。 – svick

相關問題