Dans OpenMP lors de l'utilisation de omp sections
, les threads seront-ils distribués aux blocs à l'intérieur de sections, ou chaque thread sera-t-il affecté à chaque section?
Quand nthreads == 3
:
#pragma omp sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
}
Production:
id=1
id=1
Mais quand j'exécute le code suivant:
#pragma omp sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
}
#pragma omp sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
}
Production:
id=1
id=1
id=2
id=2
De ces sorties, je ne peux pas comprendre quel est le concept de sections dans OpenMP.
Le code posté par l'OP ne s'exécutera jamais en parallèle, car le mot clé parallel
n'apparaît pas. Le fait que l'OP ait des identifiants différents de 0 montre que son code a probablement été intégré dans une directive parallèle. Cependant, ce n'est pas clair de son poste, et pourrait confondre les débutants.
L'exemple raisonnable minimum est (pour le premier exemple publié par l'OP):
#pragma omp parallel sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
}
Sur ma machine, cela imprime
id = 0,
id = 1,
montrant que les deux sections sont exécutées par des threads différents.
Il convient de noter que ce code ne peut cependant pas extraire plus de parallélisme que deux threads: s'il est exécuté avec plus de threads, les autres threads n'ont aucun travail à faire et resteront inactifs.
L'idée des sections parallèles est de donner au compilateur une indication que les différentes sections (internes) peuvent être exécutées en parallèle, par exemple:
#pragma omp parallel sections
{
#pragma omp section
{
/* Executes in thread 1 */
}
#pragma omp section
{
/* Executes in thread 2 */
}
#pragma omp section
{
/* Executes in thread 3 */
}
/* ... */
}
Il s'agit d'un indice pour le compilateur et il n'est pas garanti qu'il se produise, bien qu'il le devrait. Votre sortie est en quelque sorte ce qui est attendu; il indique qu'il y a #sections en cours d'exécution dans l'ID de thread 1 et dans le thread 2. L'ordre de sortie n'est pas déterministe car vous ne savez pas quel thread s'exécutera en premier.
Changer la première ligne de
#pragma omp sections
dans
#pragma omp sections parallèles
La directive "parallèle" garantit que les deux sections sont affectées à deux threads. Ensuite, vous recevrez l'id de sortie suivant = 0, id = 1,
Il manque le mot clé parallel
. Le mot clé parallel
déclenche l'exécution openmp en parallèle.
Selon norme OpenMP 3.1 , section 2.5.2 (accentuation du mien):
La construction des sections est une construction de partage de travail non itérative qui contient un ensemble de blocs structurés qui doivent être distribués et exécutés par les threads d'une équipe . Chaque bloc structuré est exécuté une fois par l'un des threads de l'équipe dans le cadre de sa tâche implicite.
...
Chaque bloc structuré dans la construction des sections est précédé d'une directive de section sauf éventuellement le premier bloc, pour lequel une directive de section précédente est facultative. La méthode de planification des blocs structurés parmi les threads de l'équipe est définie par l'implémentation . Il y a une barrière implicite à la fin d'une construction de sections sauf si une clause nowait est spécifiée.
Donc, en appliquant ces règles à votre cas, nous pouvons affirmer que:
sections
sont exécutés une fois, par un thread . En d'autres termes, vous avez toujours quatre impressions, quel que soit le nombre de filssections
seront exécutés (dans un ordre non déterministe) avant les blocs du second sections
(également exécuté dans un ordre non déterministe). Cela est dû à la barrière implicite à la fin des constructions de travail partagéVotre sortie est donc due à la façon dont votre ordonnanceur a décidé d'affecter les différents blocs aux threads de l'équipe.
Il peut être utile d'ajouter plus d'informations à la ligne de sortie et d'ajouter plus de sections (si vous avez le nombre de threads)
#pragma omp parallel sections
{
#pragma omp section
{
printf ("section 1 id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("section 2 id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("section 3 id = %d, \n", omp_get_thread_num());
}
}
Ensuite, vous pouvez obtenir une sortie plus intéressante comme celle-ci:
section 1 id = 4,
section 3 id = 3,
section 2 id = 1,
qui montre comment les sections peuvent être exécutées dans n'importe quel ordre, par n'importe quel thread disponible.
Notez que 'nowait' indique au compilateur que les threads n'ont pas besoin d'attendre pour quitter la section. À Fortran, 'nowait' va à la fin de la boucle ou de la section, ce qui rend cela plus évident.