2010-03-08 9 views
3

PLINQ를 사용하여 병렬 실행이 지연 실행을 통해 어떻게 작동하는지 이해하려고합니다. 다음은 간단한 예입니다.PLINQ 지연 실행

string[] words = { "believe", "receipt", "relief", "field" }; 
bool result = words.AsParallel().Any(w => w.Contains("ei")); 

는 LINQ로, 나는 실행이 "영수증"값에 도달 값의 나머지 부분에 대한 쿼리를 실행하지 않고, true를 돌려 기대.

우리가 이것을 병렬로 수행하면 "relief"의 평가가 "receipt"결과가 반환되기 전에 시작되었을 수 있습니다. 그러나 "영수증"이 참된 결과를 초래한다는 것을 쿼리가 알게되면 다른 스레드가 즉시 응답 할 것입니까?

필자의 경우 "모든"테스트가 매우 비싸고 다른 작업을 실행하기 위해 프로세서를 비울 수 있기 때문에 이는 중요합니다.

답변

4

불행히도 다른 스레드는 즉시 "항복"하지 않습니다.

Any()이 유효한 요소를 찾으면 PLINQ 스케줄러는 새로운 요소를 확인하기 위해 새 스레드 예약을 중지합니다. 기존 파티셔너는 취소 요청을 수신하므로 해당 파티션이 다른 항목의 Any()을 호출하지 못합니다. 그들이 다른 스레드가 성공했음을 알 수있는 방법이 없기 때문에

그러나, 현재 당신의 Any() 방법 내에서 람다 식 을 실행하는 모든 스레드가 여전히 실행됩니다. 새 스레드가 Any()을 호출하지 못하도록하지만 "매우 비싼"대리자의 스레드를 모두 취소 할 수는 없습니다. 보조 노트에

:

PLINQ, LINQ는 달리 객체에 정말 지연된 실행을 사용하지 않습니다. IEnumerable<T>에서 AsParallel()을 호출하면 생성되는 ParallelQuery<T>이 실제로 루틴을 병렬로 처리하기 시작합니다. 연기 된 실행은 PLINQ의 효율성을 크게 떨어 뜨립니다. 작업 파티셔를 미리 작성하고 스케줄링하지 않고는 병렬로 스케줄하는 것이 불가능하기 때문입니다.


편집 :

이 생각 후 - 당신의 람다가 매우 비싼 경우가 CancellationToken 사용을 고려할 수 있습니다. 나는 구체적으로 약 how cancellation in PLINQ works에 대해 블로깅했다. 일반적으로 토큰을 사용하고 ThrowIfCancellationRequested()으로 전화하면됩니다. 그러나 CancellationToken을 사용하고 IsCancellationRequested을 확인하면 람다를 "일찍 종료"할 수 있으므로 더 빨리 백그라운드 처리를 중지 할 수 있습니다.

+0

http://msdn.microsoft.com/en-us/library/dd997425(VS.100).aspx에 따르면 지연 실행 원칙은 PLINQ와 여전히 관련이 있습니다. 측면 지점? – tbischel

+0

@tbischel : 그들은하고, 그들은하지 않습니다 ... 그 의견은 약간 오해의 소지가 있습니다. 차이점은 LINQ에서 각 요소는 요청한 대로만 실행된다는 것입니다 (지연됨). PLINQ에서 FIRST 요청을하면,'Partitioner '이 설정되어 작업을 여러 스레드로 예약하기 시작합니다. 최종 누적 결과는 요청 될 때까지 뒤로 밀리지 않지만 요소에 대한 요청보다 먼저 처리가 발생합니다. (결과의 요소 1을 요청하면 요소 1,2,3 및 4가 모두 예약되고 즉시 "작업"이 시작될 수 있습니다 ...) –