2 votes

Division OpenMP de la boucle sur les cœurs

J'essaie d'exécuter une application en parallèle en utilisant les instructions sse et openmp. Concernant la partie openmp j'ai du code comme :

for(r=0; r<end_condition; r++){
    .. several nested for loops inside ..
}

Je veux diviser cette boucle sur r sur plusieurs cœurs, et par exemple en utilisant deux cœurs, un cœur devrait exécuter r=0 r=condition_finale/2-1 et l'autre r=condition_finale/2 r=condition_finale-1. Il n'y a pas de communication entre les itérations de la boucle, elles peuvent donc être exécutées en parallèle. À la fin de la boucle r, les résultats doivent être synchronisés.

Comment puis-je le diviser sur les cœurs de cette façon en utilisant les directives openmp ? Dois-je dérouler la boucle sur r et utiliser les sections openmp ?

Merci d'avance

2voto

kronos Points 1295

Avec le code suivant, le compilateur génère une région parallèle, qui est exécutée par N threads.

omp_set_num_threads(N);

#pragma omp parallel for
for(int r = 0; r < end_condition; ++r)
{
    .. several nested for loops inside ..
}

Chaque thread exécute un sous-ensemble de end_condition. Notez que votre variable de comptage r est maintenant déclarée dans la portée de omp parallel for. Maintenant, chaque thread a sa propre variable de comptage.

Le même objectif peut être atteint en utilisant le pragma parallel, et non le for parallel, comme ceci :

omp_set_num_threads(N);
#pragma omp parallel private(r)
{
   int tid = omp_get_thread_num();
   for(r = (end_condition/N) * tid; r < (end_condition/N) * (tid+1) ; ++r)
   {
    .. several nested for loops inside ..
   }
}

Bien sûr, uniquement lorsque end_condition%N = 0, mais vous devriez comprendre le principe. Ici la variable r est explicitement marquée comme privée pour le thread et peut être déclarée où vous voulez. Le compilateur va générer une copie pour chaque thread.

1voto

Bort Points 1242

Vous pouvez y parvenir en ajoutant :

#pragma omp parallel for
for(r=0; r<end_condition; r++){
    .. several nested for loops inside ..
}

Vous devez cependant vous assurer de ce qui est partagé et de ce qui est privé dans votre boucle. Bien que cela ne garantisse pas que r soit divisé comme vous l'avez mentionné. Si vous voulez l'avoir de cette manière explicite, vous pouvez utiliser des tâches. Mais faire cela à la main n'est pas vraiment pratique et je ne peux pas le recommander.

0voto

excray Points 766

Vous pouvez définir le nombre de fils que la boucle for doit créer. Et pour chaque thread, vous pouvez spécifier la taille du chunk.

0voto

Violet Giraffe Points 5764

Je peux seulement ajouter que vous pourriez avoir des problèmes si différentes itérations de la boucle prennent un temps différent - dans ce cas vous voudriez ajouter schedule (dynamic) :

#pragma omp parallel for schedule (dynamic)
for(r=0; r<end_condition; r++){
    .. several nested for loops inside ..
}

Notez également que la barrière est automatiquement ajoutée à la fin de la boucle afin d'être sûr que l'exécution ne se poursuit que lorsque toutes les itérations sont terminées. Si cela n'est pas souhaité (vous avez d'autres travaux à effectuer en parallèle avec une boucle) - ajoutez nowait à la for paramètres de la directive. Vous pouvez ensuite demander la synchronisation avec #pragma omp barrier .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X