95 votes

En quoi les clauses firstprivate et lastprivate sont-elles différentes des clauses private d'OpenMP ?

J'ai consulté les définitions officielles, mais je suis toujours aussi confus.

firstprivate : Spécifie que chaque thread doit avoir sa propre instance d'une variable, et que la variable doit être initialisée avec la valeur de la variable, car elle existe avant la construction parallèle.

Pour moi, ça ressemble beaucoup à du privé. J'ai cherché des exemples, mais je n'arrive pas à comprendre en quoi c'est spécial ou comment on peut l'utiliser.

lastprivate : Spécifie que la version de la variable dans le contexte englobant est égale à la version privée du thread qui exécute la dernière itération (construction for-loop) ou la dernière section (sections #pragma).

J'ai l'impression de comprendre un peu mieux cette question grâce à l'exemple suivant :

#pragma omp parallel
{
   #pragma omp for lastprivate(i)
      for (i=0; i<n-1; i++)
         a[i] = b[i] + b[i+1];
}
a[i]=b[i];

Donc, dans cet exemple, je comprends que lastprivate permet i pour être retourné en dehors de la boucle comme la dernière valeur qu'il était.

Je viens de commencer à apprendre OpenMP aujourd'hui.

196voto

Hristo Iliev Points 29262

private ne sont pas initialisées, c'est-à-dire qu'elles commencent avec des valeurs aléatoires comme n'importe quelle autre variable locale automatique (et elles sont souvent implémentées en utilisant des variables automatiques sur la pile de chaque thread). Prenons l'exemple de ce programme simple :

#include <stdio.h>
#include <omp.h>

int main (void)
{
    int i = 10;

    #pragma omp parallel private(i)
    {
        printf("thread %d: i = %d\n", omp_get_thread_num(), i);
        i = 1000 + omp_get_thread_num();
    }

    printf("i = %d\n", i);

    return 0;
}

Avec quatre fils, cela donne quelque chose comme :

thread 0: i = 0
thread 3: i = 32717
thread 1: i = 32717
thread 2: i = 1
i = 10

(another run of the same program)

thread 2: i = 1
thread 1: i = 1
thread 0: i = 0
thread 3: i = 32657
i = 10

Cela démontre clairement que la valeur de i est aléatoire (non initialisée) à l'intérieur de la région parallèle et que toute modification de celle-ci n'est pas visible après la région parallèle (c'est-à-dire que la variable conserve sa valeur d'avant l'entrée dans la région).

Si i est fait firstprivate il est alors initialisé avec la valeur qu'il a avant la région parallèle :

thread 2: i = 10
thread 0: i = 10
thread 3: i = 10
thread 1: i = 10
i = 10

Toujours des modifications à la valeur de i à l'intérieur de la région parallèle ne sont pas visibles après celle-ci.

Vous connaissez déjà lastprivate (et il n'est pas applicable au programme de démonstration simple, car il ne comporte pas d'éléments de répartition du travail).

Alors oui, firstprivate y lastprivate ne sont que des cas particuliers de private . La première a pour effet d'introduire des valeurs du contexte extérieur dans la région parallèle, tandis que la seconde transfère des valeurs de la région parallèle au contexte extérieur. La raison d'être de ces classes de partage de données est qu'à l'intérieur de la région parallèle, toutes les variables privées suivent celles du contexte extérieur, c'est-à-dire qu'il n'est pas possible d'utiliser une opération d'affectation pour modifier la valeur extérieure de i depuis l'intérieur de la région parallèle.

0voto

Muhammet Dabak Points 36

Vous ne pouvez pas utiliser de variable locale i avant l'initialisation, le programme donnera une erreur puisque la norme C++ 14.

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