2016-10-26 30 views
0

在LINQ查詢創建新的獨立的任務時運行LINQ查詢.asparallel,我已經使用.AsParallel如下:增加花費時間在C#

var completeReservationItems = from rBase in reservation.AsParallel() 
             join rRel in relationship.AsParallel() on rBase.GroupCode equals rRel.SourceGroupCode 
             join rTarget in reservation.AsParallel() on rRel.TargetCode equals rTarget.GroupCode 
             where rRel.ProgramCode == programCode && rBase.StartDate <= rTarget.StartDate && rBase.EndDate >= rTarget.EndDate 
             select new Object 
             { 
              //Initialize based on the query 
             }; 

然後,我創建了兩個獨立的任務,是運行它們並聯,通過相同的解釋,以兩種方法如下:

  Task getS1Status = Task.Factory.StartNew(
      () => 
      { 
       RunLinqQuery(params); 
      }); 
     Task getS2Status = Task.Factory.StartNew(
      () => 
      { 
       RunLinqQuery(params); 
      }); 

     Task.WaitAll(getS1Status, getS2Status); 

我被捕獲的定時,驚訝地看到,定時如下:

  1. 以上情形:6秒(6000毫秒)
  2. 相同的代碼,依次運行代替2-任務:50毫秒
  3. 相同的代碼,但是沒有.AsParallel()在LINQ:50毫秒

我想了解爲什麼在上述情況下這麼長時間。

+2

因爲並行並不意味着更快。如果基本操作速度很快,並且執行速度會更慢,因爲線程之間的上下文切換需要太多時間。 – tym32167

+0

@ tym32167同意,但我想知道在這種情況下將以什麼方式創建線程。因爲在我提到的情況2和3中,它仍然是一個並行操作,但速度更快。 –

回答

1

僅作爲答案發布,因爲我有一些代碼要顯示。

首先,我不知道用AsParallel()將創建多少個線程。文檔不說什麼https://msdn.microsoft.com/en-us/library/dd413237(v=vs.110).aspx

想象一下下面的代碼

void RunMe() 
{ 
    foreach (var threadId in Enumerable.Range(0, 100) 
          .AsParallel() 
          .Select(x => Thread.CurrentThread.ManagedThreadId) 
          .Distinct()) 
     Console.WriteLine(threadId); 
} 

多少線程的IDS,我們將看到什麼?對我來說,每一次會看到不同數目的線程,例如輸出:

30 // only one thread! 

下一次

27 // several threads 
13 
38 
10 
43 
30 

我認爲,線程的數量取決於當前調度。我們總是可以通過調用WithDegreeOfParallelismhttps://msdn.microsoft.com/en-us/library/dd383719(v=vs.110).aspx)方法,例如

void RunMe() 
{ 
    foreach (var threadId in Enumerable.Range(0, 100) 
          .AsParallel() 
          .WithDegreeOfParallelism(2) 
          .Select(x => Thread.CurrentThread.ManagedThreadId) 
          .Distinct()) 
     Console.WriteLine(threadId); 
} 

現在,輸出將包含最多2個線程定義的最大線程數。

7 
40 

爲什麼這麼重要?正如我所說,線程的數量可以直接影響性能。 但是,這不是所有的問題。在你的1場景中,你正在創建新的任務(這將在線程池中執行,並且可能會增加額外開銷),然後,你打電話給Task.WaitAll。看看它的源代碼https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,72b6b3fa5eb35695,我確定那些for循環任務會增加額外的開銷,並且在AsParallel會在第一個任務內佔用太多線程的情況下,下一個任務可以連續開始。此外,這可能會發生,所以,如果您將運行您的1場景1000次,可能會得到非常不同的結果。

所以,我最後一個說法是你試着測量並行代碼,但很難做到這一點。我不推薦儘可能多地使用並行的東西,因爲如果你不確切地知道你在做什麼,它可能會引起性能下降。