2013-01-17 2 views
3

Je suis assis avec quelques trucs ici essayant de rendre le travail orphelin, et réduire les frais généraux en réduisant les appels de #pragma omp parallel. Ce que je suis en train est quelque chose comme:pragma omp pour l'intérieur pragma omp maître ou single

#pragma omp parallel default(none) shared(mat,mat2,f,max_iter,tol,N,conv) private(diff,k) 
{ 
#pragma omp master // I'm not against using #pragma omp single or whatever will work 
{ 
while(diff>tol) { 
    do_work(mat,mat2,f,N); 
    swap(mat,mat2); 
    if(!(k%100)) // Only test stop criteria every 100 iteration 
     diff = conv[k] = do_more_work(mat,mat2); 
    k++; 
} // end while 
} // end master 
} // end parallel 

Le do_work dépend de l'itération précédente de sorte que la boucle while est doit être exécuté séquentielle. Mais je voudrais être en mesure d'exécuter le parallèle'do_work', il ressemblerait à quelque chose comme:

void do_work(double *mat, double *mat2, double *f, int N) 
{ 
int i,j; 
double scale = 1/4.0; 
#pragma omp for schedule(runtime) // Just so I can test different settings without having to recompile 
for(i=0;i<N;i++) 
    for(j=0;j<N;j++) 
     mat[i*N+j] = scale*(mat2[(i+1)*N+j]+mat2[(i-1)*N+j] + ... + f[i*N+j]); 
} 

J'espère que cela peut être accompli d'une certaine façon, je ne suis pas sûr de savoir comment. Donc, toute aide que je peux obtenir est grandement appréciée (même si vous me dites que ce n'est pas possible). Btw Je travaille avec open mp 3.0, le compilateur gcc et le compilateur sun studio.

Répondre

5

La région parallèle extérieure dans votre code d'origine contient uniquement une pièce de série (#pragma omp master), ce qui n'a pas de sens et aboutit effectivement à une exécution purement sérielle (pas de parallélisme). Comme do_work() dépend de l'itération précédente, mais vous voulez l'exécuter en parallèle, vous devez utiliser la synchronisation. L'outil openmp pour cela est une barrière de synchronisation (explicite ou implicite).

Par exemple (code similaire à la vôtre):

#pragma omp parallel 
for(int j=0; diff>tol; ++j) // must be the same condition for each thread! 
#pragma omp for    // note: implicit synchronisation after for loop 
    for(int i=0; i<N; ++i) 
    work(j,i); 

Notez que la synchronisation implicite veille à ce qu'aucun fil entre dans le prochain j si un thread travaille toujours sur la j actuelle.

L'alternative

for(int j=0; diff>tol; ++j) 
#pragma omp parallel for 
    for(int i=0; i<N; ++i) 
    work(j,i); 

devrait être moins efficace, car elle crée une nouvelle équipe de threads à chaque itération, au lieu de simplement la synchronisation.

+0

Est-ce différent de simplement placer une barrière après'k ++ 'dans mon code? En outre, la barrière dans votre exemple est-elle nécessaire? n'y a-t-il pas une barrière implicite après le '# pragma omp for'? –

+0

@AndersSchou 1) ** oui, c'est très différent **: dans votre code, aucun parallélisme ne se produit car la région parallèle ne contient qu'une région 'master', qui est seulement exécutée par le thread maître (le parallélisme imbriqué dans cela est généralement ignoré). 2) oui, ** il y a une barrière implicite **. Ainsi, la barrière supplémentaire est redondante et le compilateur devrait l'optimiser. Dans tous les cas, il est utile de laisser au moins un commentaire concernant la barrière implicite (voir édition). – Walter

+0

Remerciements: D. Cela m'a donné la réponse dont j'avais besoin. –