2016-05-13 193 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位。 數49995001大於2^24(16777216)放大,所以它會被舍入到可以被精確表示的最近數,這顯然是49995000.

這就是爲什麼使用doublesum將緩解你的疼痛。不過,這不是一個真正的解決方案。減少操作要求操作必須是交換。 但是,這不一定是浮點加法的情況:如果您將百分之一,然後49995000添加到sum,則結果將與您第一次添加1和49995000並接着九十九次1:在第二種情況下不同,每個稍後的+1將如上所示向下舍入。

0

您的結果可能會根據你所寫的內容和預期四捨五入是正確的。

+0

afValueTmp [i]中的數字都是整數,49995000不超過浮點類型範圍。爲什麼有舍入問題,使結果不同? 我發現一旦我使用double和sumNoMP類型,所有結果都是正確的。 –