2009-11-28 3 views
7

IO 바인딩 작업이 있다고합시다. WithDegreeOfParallelism = 10 및 WithExecution = ForceParallelism 모드를 사용하고 있지만 여전히 쿼리는 두 개의 스레드 만 사용합니다. 왜?왜 PLINQ는 두 개의 스레드 만 사용합니까?

PLINQ는 대개 내 코어 수와 동일한 병렬 처리 수준을 선택하지만 더 높은 병렬 처리에 대한 내 특정 요청을 무시하는 이유는 무엇입니까? 당신이이 있다면

static void Main(string[] args) 
{ 
    TestParallel(0.UpTo(8)); 
} 

private static void TestParallel(IEnumerable<int> input) 
{ 
    var timer = new Stopwatch(); 
    timer.Start(); 
    var size = input.Count(); 

    if (input.AsParallel(). 
     WithDegreeOfParallelism(10). 
     WithExecutionMode(ParallelExecutionMode.ForceParallelism). 
     Where(IsOdd).Count() != size/2) 
     throw new Exception("Failed to count the odds"); 

    timer.Stop(); 
    Console.WriteLine("Tested " + size + " numbers in " + timer.Elapsed.TotalSeconds + " seconds"); 
} 

private static bool IsOdd(int n) 
{ 
    Thread.Sleep(1000); 
    return n%2 == 1; 
} 
+2

몇 개의 프로세서/코어가 있습니까? – LukeH

+2

두 명. 하지만 구체적으로 병렬 처리 수준을 10으로 지정했습니다. – ripper234

+0

I/O 바운드 작업이 있고 병렬로 여러 스레드에서 실행하면 속도가 빨라지고 실제로 I/O 바인딩이 처음에는 실제로는 아닙니다. 심하게 작성되었습니다 (예 : 비동기 대신 동기 읽기). –

답변

8

PLINQ 당신이 단지 당신의 CPU에 2 개의 코어가있는 경우는, 가능한 한 빨리 수행 할 작업을 수행하는 데 최적의 스레드 수를 찾습니다, 그 숫자는 대부분 2입니다 쿼드 코어를 사용하면 4 개의 스레드가 표시 될 가능성이 높아지지만 듀얼 코어 시스템에 4 개의 스레드를 만들면 실제로는 2 개의 스레드 만 동시에 활성화 될 수 있으므로 성능이 향상되지 않습니다.

또한 IO 기반 연산을 사용하면 추가 스레드가 수행 된 첫 번째 IO 연산을 단순히 차단할 수 있습니다.

+4

정말 내 질문에 대답하지 않습니다 - 왜 병렬 처리 수준을 구체적으로 요구하더라도 두 개의 스레드를 사용하도록 선택합니까? (업데이트 된 질문) – ripper234

+3

@ ripper234 : MSDN 설명서에서 "병렬 처리 수준은 쿼리를 처리하는 데 사용되는 최대 동시 실행 작업 수입니다 **"입니다. 'WithDegreeOfParallelism'은 PLINQ가 * 더 이상 * * * 쓰레드를 사용하지 않는다는 힌트 일뿐입니다. http://msdn.microsoft.com/en-us/library/dd383719%28VS.100%29.aspx – LukeH

+3

그래서 IO 바인딩 작업에 PLINQ를 효과적으로 사용할 수있는 방법이 없습니까? – ripper234

4

(10)는

쿼리에 를 사용하는 병렬 처리 수준을 설정 최대입니다. 병렬 처리 수준은 이고 최대 동시 처리 수는 이며 쿼리를 처리하는 데 사용됩니다. 여기에서

:

MSDN

+0

기본적으로 PLINQ는 호스트 컴퓨터의 모든 프로세서를 최대 ** 64 **까지 사용합니다. WithDegreeOfParallelism (Of TSource) 메서드를 사용하여 지정된 수의 프로세서를 사용하도록 PLINQ에 지시 할 수 있습니다. http://msdn.microsoft.com/en-us/library/dd383719.aspx –

2

PLINQ 스레드의 수를 조정한다 나타납니다. while (true) 루프에서 위의 코드를 래핑 할 때 처음 두 반복은 실행하는 데 2 ​​초가 걸리지 만 세 번째 이상에서는 단 1 초만 걸렸습니다. PLINQ는 코어가 유휴 상태이고 스레드 수가 증가했다는 것을 알았습니다. 인상적이다!

+1

이 작업을 수행하려면 WithDegreeOfParallelism을 지정해야합니다. 그렇지 않으면 PLINQ가 시스템의 코어 수로 제한됩니다. – ripper234

0

IO를 제외하고는 Rory에 동의합니다. 디스크 입출력으로 테스트하지는 않았지만, CPU에 코어가있는 것보다 네트워크 IO가 더 많은 스레드에서 더 효과적 일 수 있습니다.

간단한 테스트 (네트워크 속도가 일정하지으로 여러 번 계산 각 스레드 테스트를 실행하는 것이 더 정확한 것,하지만 여전히) 그 증명 : CDN에서 500x500px 이미지

[Test] 
    public void TestDownloadThreadsImpactToSpeed() 
    { 
     var sampleImages = Enumerable.Range(0, 100) 
      .Select(x => "url to some quite large file from good server which does not have anti DSS stuff.") 
      .ToArray();    

     for (int i = 0; i < 8; i++) 
     { 
      var start = DateTime.Now; 
      var threadCount = (int)Math.Pow(2, i); 
      Parallel.For(0, sampleImages.Length - 1, new ParallelOptions {MaxDegreeOfParallelism = threadCount}, 
         index => 
          { 
           using (var webClient = new WebClient()) 
           { 
            webClient.DownloadFile(sampleImages[index], 
                  string.Format(@"c:\test\{0}", index)); 
           } 
          }); 

      Console.WriteLine("Number of threads: {0}, Seconds: {1}", threadCount, (DateTime.Now - start).TotalSeconds); 
     } 
    } 

결과 SSD 8 코어 시스템을 사용하면 : 1 초 : 스레드 25.3904522
: 2 초 : 스레드

번호 4 초 : 9.9325681 01,238,007,316,275,523,149 스레드 10.8986233
번호 스레드 60,453,210 번호 : 8 초 : 3.7352137
스레드 번호 : 16 초 : 스레드 3.3071892
번호 : 32 초 : 3.1421797
스레드 번호 : 64 초 : 3.1161782
스레드 번호 : (128), 초 : 3.7272132는

마지막 결과가가 우리가 단지 100 이미지 : 8-64 스레드가 크지 않다를 사용하여

시간의 차이를 다운로드해야하기 때문에 내가 먼저 생각하는 그런 시간을했지만, 8 중핵 기계.그것이 2 코어 머신 (저렴한 엔드 유저 노트북)이라면, 8 스레드를 사용하도록 강요하는 것은 8 코어 머신이 64 스레드를 사용하도록 강제하는 것보다 더 많은 영향을 미칠 것이라고 생각합니다.

+0

이 숫자를 말하자면 말하자면 10,000 회 반복 했습니까? – ChrisF

+0

각 스레드 수와 함께 여러 번 테스트를 실행하는 것이 더 정확할 것이라고 언급했습니다. 어쨌든 요점은 네트워크 IO를 수행하는 경우에 대비하여 CPU 수가 적은 컴퓨터에 더 많은 스레드를 강제하는 것입니다. – Giedrius

+0

> = 8에 대해 병렬 옵션이 무시되는 것처럼 보입니다. 병렬 바디 내에서 디버깅 출력을 추가하면 한 번에 최대 8 개까지만 실행되고 조절됩니다. – crokusek

관련 문제