Dans le code C suivant j'utilise OpenMP dans une boucle imbriquée. Depuis condition de course se produit, je veux effectuer des opérations atomiques à la fin:Pourquoi le compilateur ignore-t-il les pragmas OpenMP?
double mysumallatomic() {
double S2 = 0.;
#pragma omp parallel for shared(S2)
for(int a=0; a<128; a++){
for(int b=0; b<128;b++){
double myterm = (double)a*b;
#pragma omp atomic
S2 += myterm;
}
}
return S2;
}
La chose est que #pragma omp atomic
n'a pas d'effet sur le comportement du programme, même si je l'enlève, rien ne se passe. Même si je le change en #pragma oh_my_god
, je ne reçois aucune erreur!
Je me demande ce qui ne va pas ici, si je peux dire au compilateur d'être plus strictes lors de la vérification pragma OMP ou pourquoi je ne reçois pas une erreur quand je fais le dernier changement
PS: Pour la compilation j'utiliser :
gcc-4.2 -fopenmp main.c functions.c -o main_elec_gcc.exe
PS2: Nouveau code qui me donne le même problème et basé sur l'idée de gillespie:
#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);
}
salut, 2) oui, j'ai utilisé avant réduction, mais même problème! 3) donc, il semble que ni réduction ni aide atomique ici, que se passe-t-il? – flow
@Werner: Quand j'utilise atomique, je reçois toujours la bonne réponse. Je vais ajouter mon code à ma réponse – csgillespie
votre programme fonctionne efficacement. J'ai réalisé que mon erreur précédente était due au fait que "a" et "b" devraient être définis dans le parallèle pour, et pour cela nous devons utiliser le compilateur g ++. Avant je n'utilisais que gcc. Eh bien maintenant, j'ai modifié votre code et ajouté de nouvelles choses, comme vous pouvez le voir sur l'édition de la question, PS2, mais maintenant je reçois des résultats différents complétant g ++. Est-ce dû au fait que je fais trop d'opérations? – flow