web-dev-qa-db-fra.com

Réduction avec OpenMP

J'essaie de calculer la moyenne d'une matrice 2D en utilisant openmp. Cette matrice 2D est en réalité une image.

Je suis en train de faire la division par fil des données. Par exemple, si j'ai N threads, je traite Rows/N nombre de lignes avec thread0, etc. 

Ma question est la suivante: puis-je utiliser la clause de réduction openmp avec "#pragma omp parallel"? Quelque chose comme: 

#pragma omp parallel reduction( + : sum )
{
    if( thread == 0 )
       bla bla code 
       sum = sum + val;

    else if( thread == 1 )
       bla bla code
       sum = sum + val;
}
11
mkuse

Oui, vous le pouvez - la clause de réduction est applicable à l’ensemble de la région parallèle ainsi qu’à chaque construction de partage for. Cela permet par exemple de réduction par rapport aux calculs effectués dans différentes sections parallèles (le moyen préféré pour restructurer le code):

#pragma omp parallel sections private(val) reduction(+:sum)
{
   #pragma omp section
   {
      bla bla code
      sum += val;
   }
   #pragma omp section
   {
      bla bla code
      sum += val;
   }
}

Vous pouvez également utiliser la structure de travail de partage OpenMP for pour distribuer automatiquement les itérations de boucle entre les threads de l'équipe au lieu de la réimplémenter à l'aide de sections:

#pragma omp parallel for private(val) reduction(+:sum)
for (row = 0; row < Rows; row++)
{
   bla bla code
   sum += val;
}

Notez que les variables de réduction sont privées et que leurs valeurs intermédiaires (c'est-à-dire la valeur qu'elles détiennent avant la réduction à la fin de la région parallel) ne sont que partielles et peu utiles. Par exemple, la boucle série suivante ne peut pas être (facilement?) Transformée en boucle parallèle avec une opération de réduction:

for (row = 0; row < Rows; row++)
{
   bla bla code
   sum += val;
   if (sum > threshold)
      yada yada code
}

Ici, le yada yada code doit être exécuté à chaque itération une fois que la valeur accumulée de sum a passé la valeur de threshold. Lorsque la boucle est exécutée en parallèle, les valeurs privées de sum peuvent ne jamais atteindre threshold, même si leur somme atteint.

18
Hristo Iliev

Dans votre cas, le sum = sum + val pourrait être interprété comme val[i] = val[i-1] + val[i] dans un tableau 1-d (ou val[rows][cols] = val[rows][cols-1] + val[rows][cols] dans un tableau 2-d) qui correspond à un calcul prefix sum .

La réduction est une des solutions pour la somme de préfixes, vous pouvez utiliser la réduction pour n’importe quel opérateur commutatif-associatif tel que '+', '-', '*', '/'.

0
Charles Chow