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 que
#pragma omp critical
g_qCount++;
?
la source
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 que
#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 d'OpenMP est complètement générale - elle peut entourer n'importe quel bloc de code arbitraire. Cependant, vous payez pour cette généralité en encourant des frais généraux importants chaque fois qu'un thread entre et sort de la section critique (en plus du coût inhérent de la sérialisation).
(De plus, dans OpenMP, toutes les sections critiques sans nom sont considérées comme identiques (si vous préférez, il n'y a qu'un seul verrou pour toutes les sections critiques sans nom), de sorte que si un thread est dans une section critique [sans nom] comme ci-dessus, aucun thread ne peut entrer dans aucun [sans nom] section critique. Comme vous pouvez le deviner, vous pouvez contourner ce problème en utilisant des sections critiques nommées).
Une opération atomique a une surcharge beaucoup plus faible. Lorsqu'il est disponible, il tire parti du matériel fournissant (par exemple) une opération d'incrémentation atomique; dans ce cas, il n'y a pas de verrouillage / déverrouillage nécessaire pour entrer / sortir de la ligne de code, il fait juste l'incrément atomique avec lequel le matériel vous dit que vous ne pouvez pas être interféré.
Les avantages sont que la surcharge est beaucoup plus faible, et un thread étant dans une opération atomique ne bloque aucune opération atomique (différente) sur le point de se produire. L'inconvénient est l'ensemble restreint d'opérations prises en charge par atomic.
Bien sûr, dans les deux cas, vous engagez le coût de la sérialisation.
++
et*=
) et que si elles ne sont pas prises en charge par le matériel, elles peuvent être remplacées par descritical
sections.Dans OpenMP, toutes les sections critiques sans nom s'excluent mutuellement.
La différence la plus importante entre critique et atomic est qu'atomic ne peut protéger qu'une seule affectation et que vous pouvez l'utiliser avec des opérateurs spécifiques.
la source
Section critique:
Peut être étendu pour sérialiser des groupes de blocs en utilisant correctement la balise "name".
Ralentissez!
Fonctionnement atomique:
Est beaucoup plus rapide!
Assure uniquement la sérialisation d'une opération particulière.
la source
Le moyen le plus rapide n'est ni critique ni atomique. Approximativement, l'addition avec section critique est 200 fois plus chère qu'une addition simple, l'addition atomique est 25 fois plus chère qu'une addition simple.
L'option la plus rapide (pas toujours applicable) est de donner à chaque thread son propre compteur et d'effectuer une opération de réduction lorsque vous avez besoin de la somme totale.
la source
Les limites de
atomic
sont importantes. Ils doivent être détaillés sur les spécifications OpenMP . MSDN propose une feuille de triche rapide car je ne serais pas surpris si cela ne changera pas. (Visual Studio 2012 a une implémentation OpenMP de mars 2002.) Pour citer MSDN:Je recommande d'utiliser
atomic
quand vous le pouvez et de nommer les sections critiques autrement. Les nommer est important; vous éviterez ainsi de déboguer les maux de tête.la source
Déjà de bonnes explications ici. Cependant, nous pouvons plonger un peu plus profondément. Pour comprendre la différence fondamentale entre les concepts de section atomique et critique dans OpenMP, nous devons d'abord comprendre le concept de verrouillage . Voyons pourquoi nous devons utiliser des verrous .
Afin de synchroniser les threads dans un programme multi-thread, nous utiliserons lock . Lorsque l'accès doit être limité par un seul thread à la fois, les verrous entrent en jeu. L' implémentation du concept de verrouillage peut varier d'un processeur à l'autre. Voyons comment un simple verrou peut fonctionner d'un point de vue algorithmique.
L'algorithme donné peut être implémenté dans le langage matériel comme suit. Nous supposerons un seul processeur et analyserons le comportement des verrous. Pour cette pratique, supposons l'un des processeurs suivants: MIPS , Alpha , ARM ou Power .
Ce programme semble être OK, 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 égale à zéro. Si deux threads exécutent ce code, l'un peut atteindre le SW R1, verrouiller avant que l'autre ne lise la variable de verrouillage . Ainsi, tous deux pensent que la serrure est libre. Pour résoudre ce problème, une autre instruction est fournie plutôt que de simples LW et SW . Il s'agit d'une instruction Read-Modify-Write . Il s'agit d'une instruction complexe (composée de sous-instructions) qui garantit que la procédure d' acquisition de verrouillage est effectuée par un seulfil à la fois. La différence de lecture-modification-écriture par rapport aux instructions simples de lecture et d' écriture est qu'il utilise une méthode différente de chargement et de stockage . Il utilise LL (Load Linked) pour charger la variable de verrouillage et SC (Store Conditional) pour écrire dans la variable de verrouillage. Un registre de lien supplémentaire est utilisé pour garantir que la procédure d'acquisition de verrouillage est effectuée par un seul thread. L'algorithme est donné ci-dessous.
Lorsque le registre de lien 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'accès à la variable de verrouillage est acquise.
La principale différence entre critique et atomique vient de l'idée que:
L'utilisation d'une nouvelle variable pour les verrous conduira à une section critique , tout en utilisant la directive réelle variable 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 des performances médiocres 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 le atomique lorsqu'une région plus complexe en calcul est effectuée par la section intensive. directive chaque fois que vous souhaitez effectuer un seul calcul (x ++, x--, ++ x, --x, etc.) et d'utiliser critique
la source
atomic est relativement efficace lorsque vous devez activer l'exclusion mutuelle pour une seule instruction, ce qui n'est pas le cas pour omp critical.
la source
atomic est une seule instruction Section critique, c'est-à-dire que vous vous verrouillez pour une seule exécution d'instruction
la section critique est un verrou sur un bloc de code
Un bon compilateur traduira votre deuxième code de la même manière qu'il fait le premier
la source