2016-10-26 1 views
0

В LINQ запроса, я использовал .AsParallel следующим образом:Увеличение времени, затраченного для запуска LINQ .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); 
} 

Сколько потока иды мы увидим? Для меня каждый раз будет видеть разное количество нитей, пример вывода:

30 // only one thread! 

В следующий раз

27 // several threads 
13 
38 
10 
43 
30 

Я думаю, количество потоков зависит от текущего планировщика. Мы всегда можем определить максимальное число потоков с помощью вызова метода WithDegreeOfParallelism (https://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 раз, возможно, вы получите очень разные результаты.

Итак, мой последний аргумент в том, что вы пытаетесь измерить параллельный код, но очень сложно сделать это правильно. Я не рекомендую использовать параллельный материал столько, сколько вы можете, потому что он может повысить производительность, если вы точно не знаете, что вы делаете.

Смежные вопросы