web-dev-qa-db-fra.com

En quoi les clauses firstprivate et lastprivate sont-elles différentes des clauses privées dans OpenMP?

J'ai regardé les définitions officielles, mais je suis encore assez 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, cela ressemble beaucoup à du privé. J'ai cherché des exemples, mais je ne semble pas comprendre à quel point c'est spécial ou comment il peut être utilisé.

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

J'ai l'impression de mieux comprendre celui-ci à cause de 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 d'être renvoyé en dehors de la boucle comme dernière valeur.

Je viens de commencer à apprendre OpenMP aujourd'hui.

67
SaiyanGirl

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

#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, il produit 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 ses modifications ne sont pas visibles après la région parallèle (c'est-à-dire que la variable conserve sa valeur avant d'entrer dans la région).

Si i est fait firstprivate, alors il est 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

Les modifications de la valeur de i à l'intérieur de la région parallèle ne sont toujours pas visibles après.

Vous connaissez déjà lastprivate (et il n'est pas applicable au programme de démonstration simple car il manque de constructions de partage de travail).

Alors oui, firstprivate et lastprivate ne sont que des cas particuliers de private. Le premier a pour effet de ramener des valeurs du contexte extérieur dans la région parallèle tandis que le second transfère des valeurs de la région parallèle au contexte extérieur. La logique derrière ces classes de partage de données est qu'à l'intérieur de la région parallèle, toutes les variables privées masquent 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 de l'intérieur du région parallèle.

128
Hristo Iliev

firstprivate et lastprivate ne sont que des cas particuliers de private.

Le premier a pour effet de ramener des valeurs du contexte extérieur dans la région parallèle tandis que le second transfère des valeurs de la région parallèle au contexte extérieur.

3
Amol Jain