2014-06-07 4 views
2

저는 C#의 초보자이며 오래된 DSP, VB6 코드를 번역하면서이 언어가 제공하는 가능성을 활용하고 싶습니다. 특히 시간이 많이 소요되는 계산을 빠르게 처리하기 위해 병렬 처리를 사용하려고합니다.C# Parallel.For 예기치 않은 결과가 발생했습니다.

다음은 현재 테스트중인 (단순화 된) 코드입니다.

"1 ° 병렬 코드 OK"섹션은 문제없이 작동합니다.

"2 단계 병렬 코드 오류 결과"섹션은 "Sequential code OK"섹션과 동일해야하며 순차 버전보다 훨씬 빠르지 만 예상되는 결과는 반환하지 않습니다.

왜? 내가 어디서 잘못한거야?

 double[] Omega = new double[NFreq + 1]; 
    double[,] SinOmT = new double[NFreq + 1, NVAL]; 
    double[,] CosOmT = new double[NFreq + 1, NVAL]; 

double OmT; 

    // 1° Parallel code OK: 
     Parallel.For(0, NFreq + 1, JF => 
    { 
     Omega[JF] = PI2 * Freq[JF]/Fs; 
    }); 

    // Sequential code OK: 
    for (int JF = 1; JF <= NFreq; JF++) 
    { 
     for (int JD = 0; JD < NVAL; JD++) 
     { 
      OmT = Omega[JF] * (double)(JD); 
      SinOmT[JF, JD] = Math.Sin(OmT); 
      CosOmT[JF, JD] = Math.Cos(OmT); 
     } 
    } 

    // 2° Parallel code WRONG results: 
    for (int JF = 1; JF <= NFreq; JF++) 
    { 
     Parallel.For(0, NVAL, JD => 
     { 
      OmT = Omega[JF] * (double)(JD); 
      SinOmT[JF, JD] = Math.Sin(OmT); 
      CosOmT[JF, JD] = Math.Cos(OmT); 
     }); 
    } 

카오와 관심을 가져 주셔서 감사합니다.

프랑코

답변

0

변수 JF는 람다 표현식에 의해 캡처됩니다. 즉, 항상 동일한 값을 갖게됩니다. 더 나은 설명은 here을 참조하십시오.

4

변수 OmT을 루프 외부에 선언하는 것은 잘못된 것입니다. 그 이유는 병렬 반복이 이에 대한 경합을하고 그 값을 예기치 않게 덮어 쓰기 때문입니다.

C#에서는 항상 가장 정확한 범위에서 변수를 선언해야합니다. 이는 병렬 코드뿐만 아니라 모든 시나리오에 해당됩니다.

 var OmT = Omega[JF] * (double)(JD); 
     SinOmT[JF, JD] = Math.Sin(OmT); 
     CosOmT[JF, JD] = Math.Cos(OmT); 
+0

테오도 로스 : 매우 효과적입니다. 정말 고마워요. 다음 단계로 넘어갑니다. –

관련 문제