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;
}
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.
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 '+', '-', '*', '/'.