2013-05-23 6 views
0

J'ai un morceau de code avec deux boucles imbriquées. Quand le premier a peu d'étapes, le second a beaucoup, et l'inverse. Je peux exécuter les deux pour les boucles avec omp pour les directives indépendamment et j'ai des résultats cohérents (et une accélération). Cependant, je voudrais:Planification OpenMP

  1. Exécutez le premier en parallèle si elle a 16 étapes ou plus
  2. courir un autre le second en parallèle (mais pas le premier, même si elle a 8 étapes)

Ce parallélisme n'est pas imbriqué, car une boucle est parallèle ou l'autre. Si je les exécute de manière indépendante et exécute top -H pour voir les threads, j'observe parfois seulement un thread, parfois plus (dans chaque cas) alors ce que je veux faire aurait du sens et améliorerait réellement la performance?

Jusqu'à présent, je l'ai fait quelque chose comme ceci:

#pragma omp parallel 
{ 
    #pragma omp for schedule(static,16) 
    for(...){ 
     /* some declarations */ 
     #pragma omp for schedule(static,16) nowait 
     for(...){ 
      /* ... */ 
     } 
    } 
} 

qui ne compile pas (à l'intérieur du partage du travail région partage du travail ne peut pas être étroitement imbriquées, critique, commandé, maître ou d'une région de tâche explicite) et qui ne se comporterait pas comme je l'ai décrit de toute façon. J'ai également essayé de réduire mais j'ai eu des problèmes avec les "/ * quelques déclarations * /", et je voudrais l'éviter puisque c'est openmp3.0 et je ne suis pas sûr que le compilateur du matériel cible supportera cela.

Des idées?

Répondre

1

Vous ne pouvez pas imbriquer des constructions de partage de travail qui se lient à la même région parallèle, mais vous pouvez utiliser le parallélisme imbriqué et désactiver de manière sélective les régions avec la clause if(condition). Si condition évalue à true à l'exécution, alors la région est active, sinon elle s'exécute en série. Il ressemblerait à ceci:

/* Make sure nested parallelism is enabled */ 
omp_set_nested(1); 

#pragma omp parallel for schedule(static) if(outer_steps>=16) 
for(...){ 
    /* some declarations */ 
    #pragma omp parallel for if(outer_steps<16) 
    for(...){ 
     /* ... */ 
    } 
} 

L'inconvénient est que la région intérieure présente une petite tête si elle n'est pas actif au moment de l'exécution. Si vous voulez de l'efficacité et que vous êtes prêt à sacrifier la maintenabilité pour cela, vous pouvez écrire deux implémentations différentes de la boucle imbriquée et la ramener à la mise en œuvre appropriée en fonction de la valeur de outer_steps.

+0

Salut et merci. En fait, j'ai fini par écrire deux régions parallèles différentes dans un if() {} else {} comme vous l'avez dit. C'est moche mais c'est assez efficace. Je vais essayer votre solution quand je chercherai quelque chose d'élégant. – Emilien