2016-05-13 17 views
1

Ich möchte die Schleifenleistung mit openmp durch einen Teil des einfachen Codes vergleichen. Aber das Ergebnis ist falsch.OpenMP für Schleife verursacht falsches Ergebnis

Ich benutze bereits Reduktion um Race Condition zu vermeiden, aber nie arbeiten.

hier ist mein Code: Vielen Dank für jede Anregung

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

'für (int k = 0; k

+0

@ Johnny Mopp danke für die Nachricht. aber nach dem Hinzufügen von ";" für die Verzögerungsschleife. das Ergebnis fehlt noch. –

+0

Ich manuell berechnen das Ergebnis ist 49995000 und sumNoMP = 49992896 sum = 49994736 ..... –

Antwort

1

Sie haben Probleme mit Gleitkomma-Genauigkeit. Gestatten Sie mir erarbeiten zu:

#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; 
} 

Das Ergebnis wird:

orig: 49995000.000000 new: 49995000.000000 diff: 0.000000 

Also, wo hat, dass +1 gehen?

Der Typ float hat nur 7 bis 8 gültige Ziffern. Es spielt keine Rolle, wo sie sich befinden, da Floats intern immer in Scientific notation als x.xxE + yy-Notation dargestellt werden, wobei x.xx 24 Bit und yy 8 Bit hat. Die Zahl 49.995.001 größer als 2^24 (16.777.216), so wird es auf die nächste Zahl gerundet werden, die genau dargestellt werden kann, die scheinbar 49995000. ist

Aus diesem Grund Ihre Schmerzen mit double für sum wird lindern. Es ist jedoch keine echte Lösung. Reduktionsoperationen haben die Anforderung, dass die Operation kommutativ sein muss. Aber das ist nicht unbedingt der Fall für Fließkomma-Addition: Wenn Sie hundert mal 1 und dann 49995000 zu sum hinzufügen, wird das Ergebnis anders als wenn Sie zuerst 1 und 49995000 hinzufügen, und dann neunundneunzig Mal 1: im zweiten Fall , alle späteren +1 werden abgerundet, wie oben gezeigt.

0

Ihre Ergebnisse richtig sein kann je nachdem, was Sie geschrieben haben, und Rundung erwartet.

+0

die Zahl in afValueTmp [i] ist alles interger und 49995000 ist nicht über Float-Typ Bereich. Warum gibt es Rundungsfragen, die das Ergebnis anders machen? Ich finde, dass sobald ich Double-Typ für Sum & SumNoMP verwenden, alle Ergebnisse richtig sein werden. –