Quelle est la différence entre atomique et critique dans OpenMP?

Quelle est la différence entre atomique et critique dans OpenMP?

je peux le faire

#pragma omp atomic g_qCount++; 

mais n’est-ce pas la même chose

 #pragma omp critical g_qCount++; 

?

    L’effet sur g_qCount est le même, mais ce qui est fait est différent.

    Une section critique OpenMP est complètement générale – elle peut entourer n’importe quel bloc de code arbitraire. Vous payez pour cette généralité, cependant, en engageant des frais généraux importants à chaque fois qu’un thread entre et quitte la section critique (en plus du coût inhérent à la sérialisation).

    (En outre, dans OpenMP, toutes les sections critiques non nommées sont considérées identiques (si vous préférez, il n’ya qu’un seul verrou pour toutes les sections critiques non nommées), de sorte que si un thread se trouve dans une section critique section critique [non nommée] Comme vous pouvez le deviner, vous pouvez contourner ce problème en utilisant des sections critiques nommées.

    Une opération atomique a des frais généraux beaucoup plus bas. Lorsqu’il est disponible, il tire parti du matériel fournissant (disons) une opération d’incrémentation atomique; Dans ce cas, il n’y a pas de locking / délocking nécessaire pour entrer / sortir de la ligne de code, mais uniquement l’incrément atomique avec lequel le matériel ne peut pas interférer.

    Les avantages sont que la surcharge est beaucoup plus faible, et un thread dans une opération atomique ne bloque aucune opération atomique (différente) sur le sharepoint se produire. L’inconvénient est l’ensemble restreint d’opérations que prend en charge l’atome.

    Bien sûr, dans les deux cas, vous devez payer le coût de la sérialisation.

    Dans OpenMP, toutes les sections critiques non nommées sont mutuellement exclusives.

    La différence la plus importante entre critique et atomique est que l’atome ne peut protéger qu’une seule affectation et que vous pouvez l’utiliser avec des opérateurs spécifiques.

    Section critique:

    • Assure la sérialisation des blocs de code.
    • Peut être étendu pour sérialiser des groupes de blocs en utilisant correctement la balise “name”.

    • Ralentissez!

    Opération atomique:

    • Est beaucoup plus rapide!

    • Seulement assure la sérialisation d’une opération particulière.

    Le moyen le plus rapide n’est ni critique ni atomique. En gros, l’addition à la section critique est 200 fois plus chère que la simple addition, l’addition atomique étant 25 fois plus chère que la simple addition.

    L’option la plus rapide (pas toujours applicable) est de donner à chaque thread son propre compteur et de réduire les opérations lorsque vous avez besoin de la sum totale.

    Les limitations de l’ atomic sont importantes. Ils doivent être détaillés sur les spécifications OpenMP . MSDN offre un aide-mémoire rapide car je ne serais pas surpris si cela ne changerait pas. (Visual Studio 2012 a une implémentation OpenMP de mars 2002.) Pour citer MSDN:

    L’expression doit avoir l’une des formes suivantes:

    x binop = expr

    x++

    ++x

    x--

    --x

    Dans les expressions précédentes: x est une expression lvalue de type scalaire. expr est une expression de type scalaire et ne fait pas référence à l’object désigné par x . binop n’est pas un opérateur surchargé et est l’un des + , * , - , / , & , ^ , | , << ou >> .

    Je recommande d'utiliser atomic quand vous le pouvez et nommé des sections critiques autrement. Les nommer est important; vous éviterez de déboguer les maux de tête de cette façon.

    Déjà de grandes explications ici. Cependant, nous pouvons plonger un peu plus loin. Pour comprendre la différence fondamentale entre les concepts de section atomique et critique dans OpenMP, nous devons d’abord comprendre le concept de locking . Passons en revue pourquoi nous devons utiliser des verrous .

    Un programme parallèle est exécuté par plusieurs threads. Des résultats déterministes se produiront si et seulement si nous effectuons une synchronisation entre ces threads. Bien entendu, la synchronisation entre les threads n’est pas toujours requirejse. Nous faisons référence à ces cas où la synchronisation est nécessaire.

    Pour synchroniser les threads dans un programme multi-thread, nous utiliserons lock . Lorsque l’access doit être restreint par un seul thread à la fois, les verrous entrent en jeu. L’implémentation du concept de locking peut varier d’un processeur à l’autre. Voyons comment un simple verrou peut fonctionner d’un sharepoint vue algorithmique.

     1. Define a variable called lock. 2. For each thread: 2.1. Read the lock. 2.2. If lock == 0, lock = 1 and goto 3 // Try to grab the lock Else goto 2.1 // Wait until the lock is released 3. Do something... 4. lock = 0 // Release the lock 

    L’algorithme donné peut être implémenté dans le langage matériel comme suit. Nous allons prendre en charge un seul processeur et parsingr le comportement des verrous en cela. Pour cette pratique, supposons l’un des processeurs suivants: MIPS , Alpha , ARM ou Power .

     try: LW R1, lock BNEZ R1, try ADDI R1, R1, #1 SW R1, lock 

    Ce programme semble être correct, mais ce n’est pas le cas. Le code ci-dessus souffre du problème précédent; synchronisation . Trouvons le problème. Supposons que la valeur initiale de lock soit zéro. Si deux threads exécutent ce code, on pourrait atteindre le SW R1, verrouiller avant que l’autre ne lise la variable de locking . Ainsi, les deux pensent que la serrure est libre. Pour résoudre ce problème, une autre instruction est fournie plutôt que de simples instructions LW et SW . C’est ce qu’on appelle l’instruction Read-Modify-Write . Il s’agit d’une instruction complexe (constituée de sous-instructions) qui garantit que la procédure d’ acquisition de verrou n’est effectuée que par un seul thread à la fois. La différence entre Read-Modify-Write et les instructions simples de lecture et d’ écriture est qu’elle utilise une méthode de chargement et de stockage différente . Il utilise LL (Load Linked) pour charger la variable de locking et SC (Store Conditional) pour écrire dans la variable de locking. Un registre de liaison supplémentaire est utilisé pour garantir que la procédure d’acquisition de locking est effectuée par un seul thread. L’algorithme est donné ci-dessous.

     1. Define a variable called lock. 2. For each thread: 2.1. Read the lock and put the address of lock variable inside the Link Register. 2.2. If (lock == 0) and (&lock == Link Register), lock = 1 and reset the Link Register then goto 3 // Try to grab the lock Else goto 2.1 // Wait until the lock is released 3. Do something... 4. lock = 0 // Release the lock 

    Lorsque le registre de liens est réinitialisé, si un autre thread a supposé que le verrou est libre, il ne pourra plus écrire la valeur incrémentée dans le verrou. Ainsi, la concurrence d’access à la variable de locking est acquise.

    La différence fondamentale entre critique et atomique vient de l’idée que:

    Pourquoi utiliser des verrous (une nouvelle variable) alors que nous pouvons utiliser la variable réelle (sur laquelle nous effectuons une opération), comme variable de locking?

    L’utilisation d’une nouvelle variable pour les verrous mènera à une section critique , tandis que l’utilisation de la variable réelle comme verrou conduira au concept atomique . La section critique est utile lorsque nous effectuons beaucoup de calculs (plus d’une ligne) sur la variable réelle. En effet, si le résultat de ces calculs ne parvient pas à être écrit sur la variable réelle, toute la procédure doit être répétée pour calculer les résultats. Cela peut entraîner de mauvaises performances par rapport à l’attente de la libération du verrou avant d’entrer dans une région hautement informatique. Ainsi, il est recommandé d’utiliser la directive atomique chaque fois que vous souhaitez effectuer un calcul unique (x ++, x–, ++ x, –x, etc.) et utiliser une directive critique lorsqu’une région plus complexe en termes de calcul est effectuée par la section intensive.

    atomique est relativement efficace lorsque vous devez activer l’exclusion mutuelle pour une seule instruction similaire n’est pas vrai pour omp critical.

    atomique est une seule instruction Critical section, c.-à-d. que vous verrouillez pour une exécution de déclaration

    section critique est un verrou sur un bloc de code

    Un bon compilateur traduira votre deuxième code de la même manière que le premier