2011-12-03 17 views
3

なぜ次の答えが同じではないのですか?階乗(パラレルとノーマル)の答えが同じではありません

ノーマルコーディング:

long sum = 0; 

for (long i = 1; i <= 10; i++) 
{ 
    long result = 1; 

    for (long j = 1; j <= i; j++) 
    { 
     result = result*j; 
    } 
    sum = sum + result; 
} 

パラレルコーディング:

long sum = 0; 

Parallel.For(1, 10, delegate(int i) 
    { 
     long result = 1; 

     Parallel.For(1, i, delegate(int j) 
      { 
       result = result*j; 
      }); 

     sum = sum + result; 
    }); 

くれ

for (long i = 1; i <= 5; i++) 
     { 
      sum = sum * i; 
     } 

Parallel.For(1, 5, delegate(int i) 
    { 
     sum = sum * i; 
    }); 
正しい方法を提示してください sumresultにアクセスし、異なるスレッドによって修正されるので、並列の

結果= 120 =正常

+0

"int"で計算可能な任意のサイズの値の場合、呼び出した並列オーバーヘッドが実際の算術を支配し、スピードアップは見られません。あなたがbignumパッケージを必要とするiの値を主張するなら、スピードアップが見込まれるでしょう。 (あなたのアルゴリズムはかなり非効率的です:それぞれのj> kに対して繰り返しkを繰り返します; kをキャッシュする方が良いでしょう!) –

答えて

5

並列バージョンで回答の24

結果は任意です。ですから、各ステップの計算と結果の集計を分けることです。結果を正しく集計するには、スレッドがsumを排他的に変更するようにロックを取得する必要があります。修正する1つの方法は、次のようになります。彼らはしばしば悪いパフォーマンスにつながるので、あなたが稀に、2つの入れ子Parallel.Forループを必要としない

long sum = 0; 
object monitor = new object(); 
Parallel.For(1, 11,() => 0L, (i, state, local) => 
{ 
    long result = 1; 

    for (long j = 1; j <= i; j++) 
    { 
     result = result*j; 
    } 
    return local + result; 
}, local => { lock (monitor) sum += local; }); 

注意。だから、最も外側のレベルにあるループがParallel.Forであり、内側にはループがあるようにしてください。forまた、いくつかのスピードアップを得るには、10よりもはるかに大きな数値でテストする必要があります。

0

私はParallelで階乗を計算する速い方法を見つけました。

public static BigInteger Factorial(int n) 
    { 
     BigInteger temp = 1; 

     Parallel.For(1, n + 1, (i) => 
     { 
      temp *= i; 
     }); 

     return temp; 
    } 
関連する問題