아래의 코드 조각의 차이점은 무엇입니까? 둘 다 스레드 풀 스레드를 사용하지 않습니까?
예를 들어 컬렉션의 각 항목에 대해 함수를 호출하려는 경우,
Parallel.ForEach<Item>(items, item => DoSomething(item));
vs
foreach(var item in items)
{
Task.Factory.StartNew(() => DoSomething(item));
}
첫 번째 옵션이 훨씬 더 좋습니다.
Parallel.ForEach는 내부적으로Partitioner<T>
컬렉션을 작업 항목으로 배포 할 수 있습니다. 항목 당 하나의 작업을 수행하지는 않지만 관련된 오 v 헤드를 줄이기 위해이를 일} 처리하십시오.
두 번째 옵션은 단일Task
컬렉션의 항목 당 결과는 (거의) 동일 할 것이지만, 특히 대규모 콜렉션의 경우보다 훨씬 많은 오버 헤드가 필요하므로 전반적인 런타임이 느려집니다.
참고 - 사용 된 파티션 관리자는 적절한 파티션 도구를 사용하여 제어 할 수 있습니다.Parallel.ForEach에 과부하, 원하는 경우. 자세한 내용은 다음을 참조하십시오.사용자 정의 파티션MSDN에서.
주된 차이점은 런타임시 두 번째가 비동기 적으로 작동한다는 것입니다. 다음을 수행하여 Parallel.ForEach를 사용하여 복제 할 수 있습니다.
Task.Factory.StartNew( () => Parallel.ForEach<Item>(items, item => DoSomething(item)));
이 작업을 수행하면 분할자를 계속 활용할 수 있지만 작업이 완료 될 때까지 차단하지 마십시오.
Parallel.ForEach는 루프가 완료 될 때까지 최적화 (새 스레드를 시작하지 않을 수도 있음)하고 루프가 완료 될 때까지 차단하고 Task.Factory는 각 항목에 대한 새 타스크 인스턴스를 명시 적으로 작성하고 완료되기 전에 리턴합니다 (비동기 타스크). Parallel.Foreach는 훨씬 효율적입니다.
나는 "Parallel.For"로 "1000000000"번, "Task"객체로 하나를 실행하는 작은 실험을했습니다.
나는 프로세서 시간을 측정하고 Parallel이 더 효율적이라는 것을 발견했다. Parallel.For는 작은 작업 항목으로 작업을 분할하고 최적의 방법으로 모든 코어에서 병렬로 실행합니다. 많은 수의 작업 개체를 만드는 동안 (FYI TPL은 내부적으로 스레드 풀링을 사용함) 각 작업마다 모든 실행을 이동하여 상자에 더 많은 스트레스를 생성합니다. 이는 아래 실험에서 분명합니다.
또한 기본 TPL을 설명하는 작은 비디오를 만들었으며 Parallel.For가 코어를보다 효율적으로 활용하는 방법을 보여주었습니다.http://www.youtube.com/watch?v=No7QqSc5cl8일반 작업 및 스레드와 비교할 때
실험 1
Parallel.For(0, 1000000000, x => Method1());
실험 2
for (int i = 0; i < 1000000000; i++)
{
Task o = new Task(Method1);
o.Start();
}
Mehthod1()
이 예에서합니까? - Zapnologica
내 생각에 가장 현실적인 시나리오는 작업에 많은 작업이 필요할 때입니다. Shivprasad의 접근 방식은 컴퓨팅 자체보다는 개체 생성 / 메모리 할당에 더 중점을 둡니다. 나는 다음과 같은 방법으로 연구를했다 :
public static double SumRootN(int root)
{
double result = 0;
for (int i = 1; i < 10000000; i++)
{
result += Math.Exp(Math.Log(i) / root);
}
return result;
}
이 방법의 실행에는 약 0.5 초가 소요됩니다.
Parallel을 사용하여 200 번 호출했습니다.
Parallel.For(0, 200, (int i) =>
{
SumRootN(10);
});
그런 다음 구식 방식으로 200 번 호출했습니다.
List<Task> tasks = new List<Task>() ;
for (int i = 0; i < loopCounter; i++)
{
Task t = new Task(() => SumRootN(10));
t.Start();
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
첫 번째 사례는 26656ms에 완료되었으며, 두 번째 사례는 24478ms에 완료되었습니다. 나는 여러 번 반복했다. 매번 두 번째 접근법이 더 빨리 끝납니다.