omp parallèle vs omp parallèle pour

105

Quelle est la différence entre ces deux?

[UNE]

#pragma omp parallel
{ 
    #pragma omp for
    for(int i = 1; i < 100; ++i)
    {
        ...
    }
}

[B]

#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
   ...
}
Hyunjik Bae
la source

Réponses:

65

Je ne pense pas qu'il y ait de différence, l'un est un raccourci vers l'autre. Bien que votre implémentation exacte puisse les traiter différemment.

Les constructions de partage de projet parallèles combinées sont un raccourci pour spécifier une construction parallèle contenant une construction de partage de projet et aucune autre instruction. Les clauses autorisées sont l'union des clauses autorisées pour les contrats parallèles et partagés.

Tiré de http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

Les spécifications d'OpenMP sont ici:

https://openmp.org/specifications/

Ade Miller
la source
66

Celles-ci sont équivalentes.

#pragma omp parallelgénère un groupe de threads, tandis que #pragma omp fordivise les itérations de boucle entre les threads générés. Vous pouvez faire les deux choses à la fois avec la #pragma omp parallel fordirective fusionnée .

Krzysztof Kosiński
la source
Dans mon code, j'utilise cette structure même. Cependant, lorsque j'utilise la schedule(static, chunk)clause dans pour directive, j'obtiens un problème. Le code fonctionne bien, mais lorsque j'invoque ce code à partir d'un programme MPI, il s'exécute dans une boucle infinie. Le compteur de boucle est nul dans toutes les itérations de cette boucle. J'ai le compteur de boucle défini comme privé dans la #pragma omp paralleldirective. Je ne sais pas pourquoi il échoue uniquement lorsque MPI appelle le code. Je suis un peu sûr que chaque processus MPI fonctionne sur un processeur différent du cluster si cela compte. Aucune idée si le calendrier est à l'origine du problème.
Rohit Banga
La même chose fonctionne très bien lorsque j'utilise la #pragma omp parallel fordirective. Il devrait y avoir une différence.
Rohit Banga
1
Mise à jour: En fait, j'observe ce problème uniquement lorsque j'utilise la clause de planification, donc je suppose que cela ne dépend pas de si j'utilise le parallèle combiné pour ou deux directives différentes.
Rohit Banga
28

Voici un exemple d'utilisation de séparés parallelet for ici . En bref, il peut être utilisé pour l'allocation dynamique de tableaux privés de threads OpenMP avant d'exécuter le forcycle dans plusieurs threads. Il est impossible de faire la même initialisation en parallel forcas.

UPD: Dans l'exemple de question, il n'y a pas de différence entre un pragma unique et deux pragmas. Mais en pratique, vous pouvez créer un comportement plus sensible aux threads avec des directives parallèles et for séparées. Un peu de code par exemple:

#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}
NtsDK
la source
9

Bien que les deux versions de l'exemple spécifique soient équivalentes, comme déjà mentionné dans les autres réponses, il y a encore une petite différence entre elles. La première version inclut une barrière implicite inutile, rencontrée à la fin du "omp for". L'autre barrière implicite se trouve à l'extrémité de la région parallèle. Ajouter "nowait" à "omp for" rendrait les deux codes équivalents, au moins du point de vue d'OpenMP. Je mentionne cela car un compilateur OpenMP pourrait générer un code légèrement différent pour les deux cas.

phadjido
la source
7

Je vois des temps d'exécution très différents lorsque je prends une boucle for dans g ++ 4.7.0 et que j'utilise

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;

for (int i = 0; i < 5000000; i++)
{
   double r1 = ((double)rand() / double(RAND_MAX)) * 5;
   double r2 = ((double)rand() / double(RAND_MAX)) * 5;
   x.push_back(r1);
   y.push_back(r2);
}

int sz = x.size();

#pragma omp parallel for

for (int i = 0; i< sz; i++)
   prod[i] = x[i] * y[i];

le code de série (non openmp) s'exécute en 79 ms. le code "parallèle pour" s'exécute en 29 ms. Si j'omets foret utilise#pragma omp parallel , le runtime atteint 179 ms, ce qui est plus lent que le code de série. (la machine a une concurrence hw de 8)

le code renvoie à libgomp

parcompute
la source
2
Je pense que c'est parce que omp parallel exécute la boucle dans un thread séparé sans le diviser en threads, donc le thread principal attend la fin du deuxième thread. et le temps passe à se synchroniser.
Antigluk
7
C'est parce que sans a, #pragma omp foril n'y a pas du tout de partage multi-thread de la boucle. Mais ce n'était pas le cas de toute façon, essayez à nouveau avec un #pragma omp forélément supplémentaire à l'intérieur du #pragm omp parallelet il devrait fonctionner de manière similaire (sinon identique) à la #pragma omp parallel forversion.
Christian Rau
2
Je vois cette réponse comme la meilleure car elle montre qu’elles ne sont pas «équivalentes»
Échec scientifique
6

Il y a évidemment plein de réponses, mais celle-ci y répond très bien (avec source)

#pragma omp forne délègue que des portions de la boucle pour différents threads de l' équipe actuelle. Une équipe est le groupe de threads exécutant le programme. Au démarrage du programme, l'équipe se compose d'un seul membre: le fil maître qui exécute le programme.

Pour créer une nouvelle équipe de threads, vous devez spécifier le mot-clé parallel. Il peut être spécifié dans le contexte environnant:

#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}

et:

Que sont: parallèle, pour et une équipe

La différence entre parallèle, parallèle pour et pour est la suivante:

Une équipe est le groupe de threads qui s'exécutent actuellement. Au début du programme, l'équipe se compose d'un seul thread. Une construction parallèle divise le thread actuel en une nouvelle équipe de threads pour la durée du bloc / instruction suivant, après quoi l'équipe se fond à nouveau en une seule. for divise le travail de la boucle for entre les threads de l'équipe actuelle.

Il ne crée pas de threads, il divise uniquement le travail entre les threads de l'équipe en cours d'exécution. parallel for est un raccourci pour deux commandes à la fois: parallel et for. Parallel crée une nouvelle équipe, et pour les scissions, cette équipe doit gérer différentes parties de la boucle. Si votre programme ne contient jamais de construction parallèle, il n'y a jamais plus d'un thread; le thread maître qui démarre le programme et l'exécute, comme dans les programmes sans thread.

https://bisqwit.iki.fi/story/howto/openmp/

fogx
la source