2016-05-13 3 views
1

ループのパフォーマンスをopenmpと単純なコードの一部で比較したい。しかし結果は間違っています。OpenMP forループで間違った結果が発生する

私は既にレースコンディションを避けるためにリダクションを使用していますが、動作しません。

は、ここに私のコードです:

void TestMP_1(){ 
    float afValueTmp[MP_TEST_NUM] = { 0 }; // MP_TEST_NUM = 10000 
    float sum = 0, sumNoMP = 0; 
    float fDiff = 0; 
    double eTDiff = 0; 
    double t0 = 0; 
    double t1 = 0; 

    for (int i = 0; i < MP_TEST_NUM; i++) 
    { 
     afValueTmp[i] = i; 
    } 

    t0 = (double)getTickCount(); 
    for (int i = 0; i < MP_TEST_NUM; i++) 
    { 
     for (int k = 0; k < MP_TEST_NUM; k++); // just for delay 

     sumNoMP += afValueTmp[i]; // equation 4 
    } 

    t0 = ((double)getTickCount() - t0)/getTickFrequency(); 
    t1 = (double)getTickCount(); 

    #pragma omp parallel for reduction(+:sum) 
    for (int i = 0; i < MP_TEST_NUM; i++) 
    { 
     for (int k = 0; k < MP_TEST_NUM; k++); // just for delay 

     sum += afValueTmp[i]; 
    } 

    t1 = ((double)getTickCount() - t1)/getTickFrequency(); 
    eTDiff = t0 - t1; // time improve 
    fDiff = sum - sumNoMP; // check result 
    printf("%.3f\n", eTDiff); 
} 
+0

for(int k = 0; k

+0

@ Johnny Moppは通知のために感謝します。しかし、 ";"遅延ループのために。結果はまだ一致しません。 –

+0

私は手動で結果が49995000 であり、sumNoMP = 49992896 sum = 49994736 ..... –

答えて

1

浮動小数点精度の問題に直面しています。私は詳しく説明しますのでご了承ください。

#include <stdio.h> 

int main(void) 
{ 
    float myOrigNumber = 49995000; 
    float myNumber = myOrigNumber + 1.; 

    printf ("orig: %f new: %f diff: %f\n", 
      myOrigNumber, myNumber, myNumber-myOrigNumber); 
    return 0; 
} 

結果は以下のようになります。だから、

orig: 49995000.000000 new: 49995000.000000 diff: 0.000000 

+1ことはどこに行きましたか?

floatタイプの有効数字は7〜8桁です。浮動小数点数は内部で常にScientific notationにx.xxE + yy表記で表されているため、x.xxは24ビット、yyは8ビットです。それは明らかにあなたの痛みを軽減しますsumためdoubleを使用して、なぜこれがある49995000.

で正確に表現することができ、最も近い数に丸められますので 番号49995001は、2^24(16777216)よりも大きくなっています。しかし、それは本当の解決策ではありません。削減操作では、操作がであり、可換型である必要があります。 浮動小数点加算の場合は必ずしもそうではありません:sumに100倍の1と49995000を加算すると、結果は最初に1と49995000を追加した場合とは異なり、2番目の場合は199後のすべての+1は、上記のように切り捨てられます。

0

あなたの結果はあなたが書かれており、丸め期待されている内容に応じて、正しいかもしれどんな提案に感謝します。

+0

afValueTmp [i]の番号はすべてintergerで、49995000はfloat型の範囲を超えていません。なぜ丸め問題があり、結果が異なるのですか? sum&sumNoMPにdouble型を使用すると、すべての結果が正しいことがわかります。 –