10

가능한 중복 :

Parallel.ForEach 대 Task.Factory.StartNew

나는 약 1,000 개의 작업을 실행할 필요가있다.ThreadPool야간 기준으로 (그 숫자는 앞으로 커질 수 있음). 각 작업은 장기 실행 작업 (웹 서비스에서 데이터 읽기)을 수행하며CPU 집약적이지 않음.Async I/O이 특정 사용 사례에 대한 옵션이 아닙니다.

주어진IList<string>매개 변수 중DoSomething(string x). 다음 두 옵션 중 하나를 선택하려고합니다.

IList<Task> tasks = new List<Task>();
foreach (var p in parameters)
{
    tasks.Add(Task.Factory.StartNew(() => DoSomething(p), TaskCreationOptions.LongRunning));
}
Task.WaitAll(tasks.ToArray());

또는

Parallel.ForEach(parameters, new ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount*32}, DoSomething);

어떤 옵션이 더 좋고 그 이유는 무엇입니까?

노트 :

대답에는 사용법과TaskCreationOptions.LongRunningMaxDegreeOfParallelism = Environment.ProcessorCount * SomeConstant.


  • @ zooone9243 : 아마도 약간의 힌트를 적어 놓은 것일 뿐이지 만 4 코어 시스템에서는 4 개의 스레드 만 동시에 실행됩니다. 메모리 공간이 부족한 경우를 제외하고는 여전히 1,000 개의 스레드를 만들 수 있지만 적절한 해결책은 풀의 스레드를 사용하는 것입니다당신이하려는 의도대로. 그것은약 1,000 개의 스레드를 실행해야합니다.나를 혼란스럽게하는 부분. - Martin Liversage
  • 비동기 I / O는 설명하지 않고 옵션이 아니라고 설명하지 마십시오. 이것은 마치X / Y 문제내가 그걸 들었다면. 비동기 I / O그만큼이러한 유형의 작업을 수행하는 올바른 방법. 귀하의 케이스에 적용되지 않는다고 확신하는 경우설명우리가 실제로 최상의 솔루션을 제공 할 수 있도록 문제를 해결하십시오. - Aaronaught
  • 그런 다음 수정하십시오. 이는 아키텍처 문제가 아니라 성능 문제입니다. TPL을 사용하여 허용 가능한 성능을 얻지 못할 것입니다 (TPLTaskParallel). 기껏해야 두 가지 중 적은 수를 선택해야합니다.악. - Aaronaught
  • 그냥 제쳐두고 나는 이것이 낡은 질문이라는 것을 알고 있습니다 : Task / Parallel은 4.0 기능입니다. async는 4.5 기능입니다 (예, CTP가 있다는 것을 알고 있습니다). 따라서 진정한 4.0 기능 만이 코드에 포함된다는 것은 신으로부터 위임 받아야 할 수 있습니다. 또는 질문자가 사용해야하는 웹 서비스 라이브러리가 제 3 자라는 점을 언급하고 그것을 수정하고 비동기로 모든 것을 꾸미는 능력은 없습니다 / 모든 곳을 기다리고 있습니다. - Mike
  • 여기서 주목해야 할 점은 Parallel.ForEach를 장기 실행 (I / O 바운드 작업)에 사용하면 스레드 스케줄러가 참을성이 없어집니다. 느린 진행이 필요한 이유는 작업이 지나치게 CPU를 많이 사용하므로 스레드 풀에 스레드를 2 분 / 분으로 추가하기 시작하기 때문입니다. 이것은 기본적으로 "누출" 병렬 foreach가 완료 될 때까지이 방식으로 스레드를로드합니다. - Steven Padfield

3 답변


35

아마 당신은이 사실을 모르고 있지만,Parallel클래스는 단순히 (복잡한) 래퍼입니다.Task사물. 궁금한 점이있는 경우Parallel클래스는Task~과 함께하는 물건TaskCreationOptions.None. 그러나, 그MaxDegreeOfParallelism작업 개체의 생성자에 전달 된 생성 옵션에 상관없이 이러한 작업 개체에 영향을줍니다.

TaskCreationOptions.LongRunning근원에 "힌트"를 준다.TaskScheduler스레드 초과 사용으로 성능이 향상 될 수 있습니다. Oversubscription은 대기 시간이 긴 스레드 (예 : I / O)에 적합합니다. 하나의 코어에 하나 이상의 스레드 (예 : 스레드가 아닌 작업)를 할당하므로 대기를 기다리지 않고 항상 할 일이 생기기 때문입니다 thread가 대기 상태의 동안 완료하는 조작. 에TaskScheduler그 (것)들을 사용하는ThreadPool, 그것의지LongRunning 작업을 자신의 전용 스레드 (작업 당 스레드가있는 유일한 경우)로 실행하십시오. 그렇지 않으면 스케줄링 및 작업 도용 (실제로는 어쨌든 여기에서 원하는 것)으로 정상적으로 실행됩니다.

MaxDegreeOfParallelism실행되는 동시 작업 수를 제어합니다. 데이터가 분할되고 처리되는 최대 분할 수를 지정하는 것과 비슷합니다. 만약TaskCreationOptions.LongRunning이 모든 작업은 한 번에 실행되는 작업의 수를 제한하는 것과 같습니다.TaskScheduler최대 동시성 레벨이 그 값으로 설정된 경우,이 예제와 비슷하다..

너는Parallel.ForEach. 그러나,MaxDegreeOfParallelism그러한 많은 수와 같으면 실제로 많은 스레드가 동시에 실행되는 것을 보장하지는 않습니다. 태스크는 여전히ThreadPoolTaskScheduler. 그 스케줄러는 가능한 한 가장 적은 양으로 한 번에 실행되는 스레드의 수입니다. 두 방법의 가장 큰 차이점은 제가 가정 한 것입니다. 당신은 당신 자신의 것을 쓸 수 있습니다.TaskScheduler그것은 병렬 처리의 최대 정도를 모방하고, 두 세계의 최고를 가졌지 만, 당신이하고 싶은 것에 무언가 의심하고 있습니다.

내 생각에 대기 시간과 실제 요청 횟수에 따라 작업을 사용하면 많은 (?) 경우에 더 나은 성능을 발휘하지만 더 많은 메모리를 사용하면 성능이 향상되지만 병렬 환경에서는 리소스 사용이보다 일관성있게 유지됩니다. 물론 비동기 I / O는이 두 가지 옵션 중 가장 뛰어난 성능을 발휘할 것입니다. 그러나 기존 라이브러리를 사용하고 있기 때문에 그렇게 할 수 없다는 것을 알고 있습니다. 불행히도, 당신이 선택한 어떤 사람이든 상관없이 평범한 공연에 머물러있을 것입니다.

실제 솔루션은 비동기 I / O를 수행하는 방법을 찾는 것입니다. 상황을 모르기 때문에 나는 그보다 더 도움이 될 수 있다고 생각지 않습니다. 프로그램 (읽기, 스레드)은 계속 실행되고 커널은 I / O 작업이 완료 될 때까지 기다립니다 (I / O 완료 포트 사용이라고도 함). 스레드가 대기 상태가 아니기 때문에 런타임은 적은 수의 스레드에서 더 많은 작업을 수행 할 수 있으며 보통 코어 수와 스레드 수 사이의 최적 관계로 끝납니다. 내가 원하는대로 많은 스레드를 추가하는 것이 더 나은 성능 (실제로 컨텍스트 스위칭과 같은 이유로 인해 종종 성능을 해칠 수 있음)과 동일하지 않습니다.

그러나이 전체 답변은 a를 결정할 때 쓸모가 없습니다.결정적인귀하의 질문에 대한 답변, 비록 그것이 당신에게 필요한 방향을 줄 수 있기를 바랍니다. 프로필을 작성할 때까지 어떤 성과가 더 좋은지 알 수 없습니다. 둘 다 시도하지 않으면 (나는 LongRunning 옵션이없는 태스크를 의미해야하며, 스케줄러가 스레드 전환을 처리하도록 함), 프로파일 링하여 가장 적합한 것이 무엇인지 판별하십시오특정 유스 케이스너는 너 자신을 파는거야.


  • 좋은 답변 주셔서 감사합니다. 나는 왜 Parallel 클래스가 Task 객체를 생성하는지에 대해 궁금해하는데, 어떻게 백그라운드 스레드를 생성하는 포어 그라운드 스레드 대 태스크 라이브러리를 생성 할 수 있으며 포어 그라운드 스레드를 생성하는 옵션을 제공하지 않는 것 같습니까? - Zaid Masud
  • @ zooone9243 - 실제로 전경 스레드를 만들지 않습니다. 대신 Wait ()을 호출하여 완료 또는 취소 될 때까지 실행을 차단합니다. - Christopher Currens
  • @ zooone9243 - 내가 만드는 것보다 조금 더 복잡합니다. 내부 동작에 대해 잘 이해하고 싶다면, 체크 아웃을 권장합니다..NET 참조 소스 - Christopher Currens

4

두 옵션 모두 사용자 시나리오에 대해 부적절합니다.

TaskCreationOptions.LongRunningTPL (TPL)은 CPU와 관련이없는 작업에 더 나은 선택입니다.Parallel클래스 / 확장)은 거의 모든 코어 (스레드가 아닌)에서 실행하여 CPU 바인딩 작업의 처리량을 최대화하기위한 것입니다.

그러나 1000 개의 작업은 허용되지 않는 숫자입니다. 그들이 모두 한꺼번에 작동하는지 여부는 문제가 아닙니다. 동기 I / O를 기다리는 100 개의 스레드조차도 견딜 수없는 상황입니다. 의견에서 알 수 있듯이 응용 프로그램은 엄청난 양의 메모리를 사용하고 문맥 전환에 거의 모든 시간을 소비하게됩니다. TPL은이 규모에 맞게 설계되지 않았습니다.

귀하의 작업이 I / O 경계에 있고 웹 서비스를 사용하는 경우,그들은- 비동기 I / O는 올바른 솔루션 일뿐만 아니라해결책. 원래 코드가없는 주요 인터페이스에 비동기 메소드를 추가하는 경우와 같이 일부 코드를 다시 설계해야하는 경우I / O 완료 포트가이 특정 유형의 동시성을 제대로 지원할 수있는 Windows 또는 .NET의 메커니즘.

비동기 I / O가 어떻게 든 "옵션이 아닌"상황을 들어 본 적이 없습니다. 이 제약에 대한 유효한 유스 케이스를 생각조차 할 수 없다. 비동기 I / O를 사용할 수없는 경우 수정해야하는 심각한 디자인 문제가 있음을 나타내며,최대한 빨리.


  •                       ... 각 웹 서비스 호출에는 값 비싼 핸드 쉐이크가 필요합니다. 연결을 설정하는 것이 진짜 킬러 다. 실제 통화보다 더 많이 그렇다. 입출력 완료 포트에 대한 지식이 제한되어 있으며이 시나리오에서 사용할 수 있습니까? 이들에 대한 좋은 참고 자료가 있으면 공유하십시오. 감사. - Zaid Masud
  • @ zooone9243, 왜 비동기 IO를 사용할 수 없다는 것을 의미하는지 모르겠다. 더 이상 말하지 않는 한 정확하게 수행하는 방법을 알려주지 못합니다. - svick
  • @svick 이러한 I / O 완료 포트에 대해 더 자세히 알아야 할 필요가 있습니다 ... 여기서 다루는 것처럼 관리되지 않는 Windows I / O 스레드를 사용하는 것에 대해 이야기하고 있습니까?blogs.msdn.com/b/ericeil/archive/2008/06/20/… - Zaid Masud
  • @ zooone9243, 아니, 사용하는 것을 의미합니다.BeginXxx()/EndXxx()방법 대신에Xxx()방법. 우리가 정확히 말하는 방법은 정확히 무엇을하고 있는지에 달려 있습니다.WebRequest또는Socket또는 어쩌면 다른 것). 그만큼Begin/End그런 다음 메소드는 내부적으로 I / O 완료 포트를 사용합니다. - svick
  • @ zooone9243 : 아마도 "웹 서비스"의 의미를 잘못 해석했을 것입니다. 여기,하지만 제 경험상 웹 서비스의 전제는 표준 웹 프로토콜과 형식 (즉, SOAP, XML, JSON, HTTP 또는 HTTPS를 통해)을 사용한다는 것입니다.돈 없음액세스 할 수있는 독점 라이브러리가 필요합니다. 소스 또는 스펙이없는 완전히 불투명 한 2 진 인코딩 RPC 서비스입니까? - Aaronaught

4

이것은 직접 비교가 아니지만 도움이 될 것 같습니다. 나는 당신이 묘사하는 것과 비슷한 것을한다. (내 경우에는 REST 호출을 제공하는 다른 쪽 끝에로드 밸런싱 서버 클러스터가있다.) 나는 좋은 결과를 얻는다.Parrallel.ForEach최적의 작업자 스레드 수를 늘리기나는 또한 다음 코드를 사용한다.내 운영 체제에 평소보다 많은 수의 엔드 포인트에 연결할 수 있다고 알려줍니다.

    var servicePointManager = System.Net.ServicePointManager.FindServicePoint(Uri);
    servicePointManager.ConnectionLimit = 250;

연결하는 각 고유 URL에 대해 한 번씩 호출해야합니다.

연결된 질문


관련된 질문

최근 질문