2012-10-09 2 views
1

.NET Framework 4.0에서 병렬 for 루프를 활용하려고합니다. 그러나 나는 그 결과 집합에 몇 가지 요소가 빠져 있다는 것을 알아 차렸다.병렬 For 루프

다음과 같이 코드 스 니펫이 있습니다. lhs.ListData은 nullable double 및 의 목록입니다. rhs.ListData은 Null 허용 Double 목록입니다. I는 "*"동작을 수행 할 때

int recordCount = lhs.ListData.Count > rhs.ListData.Count ? rhs.ListData.Count : lhs.ListData.Count; 

List<double?> listResult = new List<double?>(recordCount); 
var rangePartitioner = Partitioner.Create(0, recordCount); 

Parallel.ForEach(rangePartitioner, range => 
        { 
         for (int index = range.Item1; index < range.Item2; index++) 
         { 
          double? result = lhs.ListData[index] * rhs.ListData[index]; 
          listResult.Add(result); 
         } 
        }); 

lhs.ListData가 rhs.ListData은 7962.의 길이가 7,964 및 의 길이를 가지며, listResult 출력으로 만 7867을 갖는다. 두 입력 목록에 널 요소가 있습니다.

실행 중에 어떤 일이 일어나는지 확실하지 않습니다. 결과 집합에 더 적은 요소가 나타나는 이유가 있습니까? 조언을주세요 ...

+0

[게시물에 서명 또는 태그 라인을 사용하지 마십시오] 제발 (http://stackoverflow.com/faq#signatures). – meagar

답변

2

이 작업을 수행하는 올바른 방법은 LINQ의 IEnumerable.AsParallel() 확장자를 사용하는 것입니다. 모든 파티션 작업을 수행하며 PLINQ의 모든 내용은 본질적으로 스레드로부터 안전합니다. Zip이라는 또 다른 LINQ 확장 프로그램이 있습니다.이 확장 프로그램에서는 제공하는 기능에 따라 두 개의 컬렉션을 하나로 통합합니다. 그러나 이것은 단지 두 목록 중에서 더 짧은 길이로 이동하기 때문에 필요한 것은 아닙니다. 길지는 않습니다. 이 작업을 수행하는 것이 쉽지만 목록의 끝에 null으로 채워서 두 목록 중 짧은 목록을 길게 확장하십시오.

IEnumerable<double?> lhs, rhs; // Assume these are filled with your numbers. 
double?[] result = System.Linq.Enumerable.Zip(lhs, rhs, (a, b) => a * b).AsParallel().ToArray(); 

여기 Zip에 MSDN 페이지의 :

http://msdn.microsoft.com/en-us/library/dd267698%28VS.100%29.aspx

+0

답장을 보내 주셔서 감사합니다. 그리고 그것은 나를 위해 잘 작동합니다. 나는 항상 짧은 목록을 출력해야한다. 위의 논리를 b == 0인지 확인해야하는 부분에 대해 어떻게 변경합니까? –

+0

'(a, b) => a * b' 부분은 그냥 정규 람다이며,'Func '클래스 내의 메소드를 포함합니다. –

0

List<T> (예 : Add)의 작업이 스레드로부터 안전하지 않기 때문일 수 있습니다. 결과는 다를 수 있습니다. 이 문제를 해결하려면 잠금 장치를 사용할 수 있지만 성능이 크게 저하 될 수 있습니다. 당신은 단지 결과 목록의 각 항목은 두 개의 입력 목록에서 해당 인덱스에있는 항목의 제품되고 싶어처럼

그것은 보는 방법이 사용하는 대신 PLINQ에 대해 왜

var listResult = lhs.AsParallel() 
        .Zip(rhs.AsParallel(), (a,b) => a*b) 
        .ToList(); 

확실하지 않음 여기서 병렬 처리를 선택했습니다. 필요한 경우 벤치마킹 할 것입니다. 애플리케이션에서 실제로 병목 현상이 발생합니까?

+0

이 가설은 MSDN의'List ' 페이지에서 확인됩니다. 'List '는 동시에 읽을 수는 있지만 쓰기는 할 수 없으므로 스레드로부터 안전합니다. 목록을 잠그는 것은 그것이 제공하는 제안이기도합니다. –

0

결과를 저장하는 데 List<double?>을 사용하고 있지만 Add 메서드는 스레드로부터 안전하지 않습니다. 당신은 (대신 Add를 호출하는) 결과를 저장하기 위해 명시 적으로 인덱스를 사용할 수 있습니다

listResult[index] = result;