Странное поведение во вложенном цикле OpenMP - PullRequest
0 голосов
/ 25 января 2011

В следующей программе я получаю разные результаты (по сравнению с OpenMP), в чем причина?На данный момент я могу только думать, что, возможно, цикл слишком «большой» для потоков, и, возможно, мне следует написать его каким-то другим способом, но я не уверен, какие-либо подсказки?1004 *

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <omp.h>
    #include <math.h>

    #define NRACK 64
    #define NSTARS 1024

    double mysumallatomic_serial(float rocks[NRACK][3],float moon[NSTARS][3],float qr[NRACK],float ql[NSTARS]) {
        int j,i;
        float temp_div=0.,temp_sqrt=0.;
        float difx,dify,difz;
        float mod2x, mod2y, mod2z;
        double S2 = 0.;
    for(j=0; j<NRACK; j++){
        for(i=0; i<NSTARS;i++){     
            difx=rocks[j][0]-moon[i][0];
            dify=rocks[j][1]-moon[i][1];
            difz=rocks[j][2]-moon[i][2];
            mod2x=difx*difx;
            mod2y=dify*dify;
            mod2z=difz*difz;
            temp_sqrt=sqrt(mod2x+mod2y+mod2z);
            temp_div=1/temp_sqrt;
            S2 += ql[i]*temp_div*qr[j];     
        }
    }
    return S2;
}

double mysumallatomic(float rocks[NRACK][3],float moon[NSTARS][3],float qr[NRACK],float ql[NSTARS]) {
    float temp_div=0.,temp_sqrt=0.;
    float difx,dify,difz;
    float mod2x, mod2y, mod2z;
    double S2 = 0.;

#pragma omp parallel for shared(S2)
    for(int j=0; j<NRACK; j++){
        for(int i=0; i<NSTARS;i++){
            difx=rocks[j][0]-moon[i][0];
            dify=rocks[j][1]-moon[i][1];
            difz=rocks[j][2]-moon[i][2];
            mod2x=difx*difx;
            mod2y=dify*dify;
            mod2z=difz*difz;
            temp_sqrt=sqrt(mod2x+mod2y+mod2z);
            temp_div=1/temp_sqrt;
            float myterm=ql[i]*temp_div*qr[j];  
            #pragma omp atomic
            S2 += myterm;
        }
    }
    return S2;

int main(int argc, char *argv[]) {
float rocks[NRACK][3], moon[NSTARS][3];
float qr[NRACK], ql[NSTARS];
int i,j;

for(j=0;j<NRACK;j++){
    rocks[j][0]=j;
    rocks[j][1]=j+1;
    rocks[j][2]=j+2;
    qr[j] = j*1e-4+1e-3;
    //qr[j] = 1;
}

for(i=0;i<NSTARS;i++){
    moon[i][0]=12000+i;
    moon[i][1]=12000+i+1;
    moon[i][2]=12000+i+2;
    ql[i] = i*1e-3 +1e-2 ;
    //ql[i] = 1 ;
}
printf(" serial: %f\n", mysumallatomic_serial(rocks,moon,qr,ql));
printf(" openmp: %f\n", mysumallatomic(rocks,moon,qr,ql));
return(0);

    }
    }

Ответы [ 2 ]

0 голосов
/ 25 января 2011

У вас есть гонки данных по большинству временных переменных, которые вы используете в параллельной области - difx, dify, difz, mod2x, mod2y, mod2z, temp_sqrt и temp_div должны быть приватными. Вы должны сделать эти переменные частными, используя директиву private для параллели для директивы.

0 голосов
/ 25 января 2011

Я думаю, вы должны использовать reduction вместо общей переменной и удалить #pragma omp atomic, например:

#pragma omp parallel for reduction(+:S2)

И он должен работать быстрее, потому что нет необходимости в атомарных операциях, которые являются довольно болезненными с точки зрения производительности и синхронизации потоков.

UPDATE

Вы также можете иметь некоторые различия в результатах из-за порядка операций:

\sum_1^100(x[i]) != \sum_1^50(x[i]) + \sum_51^100(x[i])

...