2013-08-10 1 views
4

가장 좋은 방법이 무엇인지 알고 싶습니다. 또는 다음과 같이 각 루프에 대한 일반 내에서 Parallel.foreach와 Task를 사용하는 것의 차이점을 확인하는 데 도움이되는 문서/기사가 있습니다.foreach 루프 내에서 parallel.foreach와 task를 사용하는 것의 성능 차이는 무엇입니까?

경우 1 - Parallel.foreach :

Parallel.foreach 
{ 
    // Do SOmething thread safe: parsing an xml and then save 
    // into a DB Server thry respoitory approach 
} 

경우 2 - foreach는 내 작업 :

foreach 
{ 
    Task t1 = Task.factory.startNew(()=> 
    { 
    //Do the same thing as case 1 that is thread safe 
    } 
} 
Task.waitall() 
  • 내가 내 자신의 테스트를 할 않았고 결과 쇼 케이스 (1)는 비율이 추천에 관한 케이스 (2)보다 훨씬 더 잘 수행 순차를 케이스 (1) 대 케이스 대 2 = 5S : 초 : 경우에 4 4S

를 거의 1이 있지만 1과 케이스 2? 따라서 루프 내에서 병렬로 실행하려면 parallel.foreach 또는 parallel.for를 항상 사용해야 함을 의미합니까?

+2

나는 당신의 테스트 결과를 불신합니까 ... 그 숫자는 당신과 함께 경고 벨을 울려 야합니다. – usr

+0

@Will - 작업 만들기는 스레드 만들기와 매우 다릅니다. TPL의 _ deison_ etre_. –

+0

@ Will, 입력 해 주셔서 감사합니다. 저는 같은 생각을 가지고 있다고 생각합니다. 그러나 그 결과가 왜 다른지 보여줍니다. 그리고 4 번 ... – mting923

답변

1

먼저이 주제에 대한 최고의 문서는 C#을 통한 CLR의 제 5 부입니다.

http://www.amazon.com/CLR-via-C-Developer-Reference/dp/0735667454/ref=sr_1_1?ie=UTF8&qid=1376239791&sr=8-1&keywords=clr+via+c%23

둘째, 나는 단지 작업을 생성하지 않습니다 때문에 Parallel.Foreach가 더 잘 수행 할 것으로 예상하지만, 그룹화 것입니다. 제프리 리히터 (Jeffrey Richter)의 저서에서, 그는 개별적으로 시작되는 작업이 스레드 풀 대기열에 저장 될 것이라고 설명합니다. 실제 스레드 풀 대기열을 잠그는 데 약간의 오버 헤드가 있습니다. 이를 해결하기 위해 작업 자체에는 만드는 작업에 대한 자체 대기열이 있습니다. 작업에 의해 보유 된이 작업 하위 대기열은 실제로 잠금없이 작업을 수행 할 수 있습니다!

이 장 (27 장)을 다시 읽어야하므로 Parallel.Foreach가이 방법으로 작동하는지 확신 할 수 없지만 이것이 내가 기대하는 바입니다.

잠금 기능은 커널 레벨 구조에 액세스해야하므로 비용이 많이 든다고 그는 설명합니다.

두 경우 모두 순차적으로 처리 할 필요는 없습니다. Parallel.Foreach를 사용하면 앞서 내부 구조로 인해 foreach 키워드보다 순차적으로 처리 할 가능성이 적습니다.

+0

나는 책을 아직 읽지 않고 있지만 parallel.each의 '그룹'기능에 대한 귀하의 요점에 동의합니다. 내 병렬에서는. 중요한 부분이 될 블록을 기대 하긴하지만 parallel.foreach 방식으로 구현하는 것은 아닙니다. 나는이 장을 읽은 후에 더 많은 것을 말씀 드리고 싶습니다. 추천서를 보내 주셔서 감사합니다.이 책은 내 지식을 강화하는 데 매우 유망한 것으로 보입니다. – mting923

+0

필자는 Parallel의 컨텍스트에서 Task 대기열 메커니즘에 대해 직접 이야기하지는 않겠지 만 그 장 또는 다음 장의 어느 쪽인지에 있습니다. –

0

몇 개의 작업을 실행하고 있습니까? 새로운 작업을 만드는 것만으로도 충분히 반복적으로 작업 할 수 있습니다. 즉, 다음 블록은 첫 번째 블록에서 15ms, 두 번째 블록에서 1 초 이상 실행되며 두 번째 블록은 작업을 실행하지 않습니다. Start의 주석 처리를 제거하면 시간이 거의 3 초가됩니다. WaitAll은 소량 만 추가합니다. Parallel.ForEach()이 무엇

static class Program 
{ 
    static void Main() 
    { 
     const int max = 3000000; 
     var range = Enumerable.Range(0, max).ToArray(); 
     { 
      var sw = new Stopwatch(); 
      sw.Start(); 
      Parallel.ForEach(range, i => { }); 
      sw.Stop(); 
      Console.WriteLine(sw.ElapsedMilliseconds); 
     } 
     { 
      var tasks = new Task[max]; 
      var sw = new Stopwatch(); 
      sw.Start(); 
      foreach (var i in range) 
      { 
       tasks[i] = new Task(()=> { }); 
       //tasks[i].Start(); 
      } 
      //Task.WaitAll(tasks); 
      sw.Stop(); 
      Console.WriteLine(sw.ElapsedMilliseconds); 
     } 
    } 
} 
+0

고마워요 샘플 코드는 입력하기 전에 시도해 볼 것입니다. 그러나 각 루프의 평균 시간도 비교할 것입니다. – mting923

1

Task의 작은 번호가 루프의 반복을 처리하기 위해 생성하는 것입니다. Task은 비교적 저렴하지만 무료는 아니므로 성능이 향상됩니다. 루프의 본문이 신속하게 실행되므로 개선 작업이 실제로 크게 수행 될 수 있습니다. 이것은 관찰하고있는 행동에 대한 가장 가능성있는 설명입니다.

+0

나는 마지막 두 문장을 이해하고 있는지 잘 모르겠다. 어떤 구현을 '너의 몸'에 대해 말하는거야? parallel.foreach? 또는 foreach 루프 내의 작업? – mting923

+0

@ mting923 루프의 반복이 아니라 전체'Task'를 의미합니다. – svick

관련 문제