2011-01-18 1 views
30

L'instruction de pause est couramment utilisée dans la boucle de test spinlock, quand un autre thread possède le spinlock, pour atténuer la boucle serrée. On dit qu'il est équivalent à certaines instructions NOP. Quelqu'un pourrait-il me dire exactement comment cela fonctionne pour l'optimisation de spinlock? Il me semble que même les instructions NOP sont une perte de temps CPU. Vont-ils diminuer l'utilisation du processeur?Comment l'instruction de pause x86 fonctionne-t-elle dans spinlock * et * peut-elle être utilisée dans d'autres scénarios?

Une autre question est celle que je pourrais utiliser une instruction de pause à d'autres fins similaires. Par exemple, j'ai un thread occupé qui continue à balayer certains endroits (par exemple une file d'attente) pour récupérer de nouveaux nœuds; cependant, parfois la file d'attente est vide et le thread est en train de gaspiller du temps CPU. dormir le fil et le réveiller par d'autres threads peut être une option, mais le fil est critique, donc je ne veux pas le faire dormir. Est-ce que l'instruction de pause peut fonctionner pour mon but d'atténuer l'utilisation du processeur? Actuellement, il utilise 100% cpu d'un noyau physique?

Merci.

+0

Le point d'un spin-wait * est * de perdre du temps CPU. Burning 100% core est * mauvais * pour perf, il empêche un autre thread de donner quelque chose à votre travailleur. –

Répondre

21

PAUSE indique à la CPU qu'il s'agit d'une boucle d'attente spinlock afin que la mémoire et les accès au cache puissent être optimisés. Voir aussi pause instruction in x86 pour plus de détails sur l'évitement de la mauvaise spécification de l'ordre de la mémoire en quittant la boucle de spin. PAUSE peut effectivement arrêter le CPU pendant un certain temps pour économiser l'énergie. Les anciens processeurs le décodent comme REP NOP, donc vous n'avez pas à vérifier si c'est supporté. Les anciennes CPU ne feront simplement rien (NOP) aussi vite que possible.

Voir aussi https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops


Mise à jour: Je ne pense pas que ce soit une bonne idée d'utiliser PAUSE dans la file d'attente de vérification à moins que vous allez faire votre file d'attente spinlock comme (et il n'y a aucun moyen évident de fais le).

Le spin depuis très longtemps est toujours très mauvais, même avec PAUSE.

+0

Oui, j'ai cette impression que PAUSE est une instruction spécialisée, donc non appropriée à d'autres fins, peut-être en raison de ses effets secondaires. Je suis intéressé par les détails. Peut-être que le manuel Intel est une bonne référence :) – Infinite

+4

BTW, PAUSE ne résoudra pas votre problème: il va arrêter le CPU pour économiser de l'énergie mais ne le reprogrammera pas pour d'autres tâches.Passer à l'intérieur de PAUSE ou faire du busyloop ne fait aucune différence, vous aurez toujours 100% de charge CPU, juste avec une consommation d'énergie plus faible. – blaze

+3

Vos deux liens sont morts maintenant. Je suggère https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops –

13

Un processeur subit une pénalité de performance sévère lorsqu'il quitte la boucle car il détecte une violation d'ordre de mémoire possible. L'instruction PAUSE donne une indication au processeur que la séquence de code est une boucle d'attente de spin. Le processeur utilise cet indice pour éviter la violation de l'ordre de la mémoire dans la plupart des situations, , ce qui améliore grandement les performances du processeur. Pour cette raison, il est recommandé qu'une instruction PAUSE soit placée dans toutes les boucles d'attente de spin. Une fonction supplémentaire de l'instruction PAUSE consiste à réduire la consommation d'énergie des processeurs Intel.

[source: manuel Intel]

1

L'instruction PAUSE semble également être utilisé dans les processeurs hyper-threading pour atténuer l'impact de la performance sur d'autres sujets hyper, probablement en renonçant à plus de temps CPU pour eux.

L'article suivant Intel décrit cela, et non recommande d'éviter étonnamment boucles d'attente occupés sur ces processeurs: https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors

1

Intel ne recommande en utilisant uniquement les instructions PAUSE lorsque la boucle de spin est très court.

Comme je l'ai compris à partir de vos questions, les attentes dans votre cas sont très longues. Dans ce cas, les boucles de spin ne sont pas recommandées.

Vous avez écrit que vous avez un "thread qui continue à balayer certains endroits (par ex.Dans ce cas, Intel vous recommande d'utiliser les fonctions de l'API de synchronisation de votre système d'exploitation, par exemple, vous pouvez créer un événement lorsqu'un nouveau nœud apparaît dans une file d'attente, et attendez simplement que vous en ayez besoin. Cet événement utilise le WaitForSingleObject(Handle, INFINITE)

Selon le Manuel d'optimisation Intel, l'instruction PAUSE est généralement utilisée avec des threads logiciels s'exécutant sur deux processeurs logiques situés dans le même cœur de processeur. Les boucles d'attente courtes ont tendance à durer entre quelques dizaines et quelques centaines de cycles (c.-à-d. entre 20 et 500 cycles de processeur), il est donc plus avantageux d'attendre en occupant le processeur que lding à l'OS. 500 cycles CPU sur un processeur Core i7 7700K à 4500 MHz est 0,0000001 secondes, c'est-à-dire 1/10000000ème de seconde: la CPU peut faire 10 millions de fois par seconde cette boucle de 500 cycles CPU.

Comme vous voyez, cette instruction PAUSE est vraiment short périodes de temps. D'autre part, chaque appel à une fonction API comme Sleep() subit le coût élevé d'un changement de contexte, qui peut être de 10000 cycles et plus; il subit également le coût de l'anneau 3 à l'anneau 0 transitions, qui peuvent être 1000+ cycles. S'il y a plus de threads, alors les cœurs du processeur (multiplié par la fonction hyperthreading, s'il y a lieu) sont disponibles, et un thread passe à un autre au milieu d'une section critique, attendant la section critique d'un autre thread peut vraiment prendre looong, au moins 10000+ cycles, de sorte que l'instructionsera futile.

S'il vous plaît voir cet article pour plus d'informations:

Lorsque la boucle d'attente devrait durer des milliers de cycles ou plus, il est préférable de céder au système d'exploitation en appelant l'une des fonctions API de synchronisation du système d'exploitation, telles que WaitForSingleObject sous Windows OS.

En conclusion: dans votre scénario, l'instruction PAUSE ne sera pas le meilleur choix, puisque votre temps d'attente est long alors que le PAUSE est prévu pour des boucles très courtes. PAUSE est juste 131 cycles SkyWell ou processeurs plus tard. Par exemple, il est juste ou 31.19ns sur Intel Core i7-7700K CPU @ 4.20GHz Kaby Lake.

Sur les processeurs antérieurs, comme Haswell, j'ai environ 9 cycles. Il est de 2,81ns sur Intel Core i5-4430 @ 3GHz. Ainsi, pour les boucles longues, il vaut mieux abandonner le contrôle à d'autres threads en utilisant les fonctions de l'API de synchronisation du SE plutôt que d'occuper le CPU avec la boucle PAUSE.

+3

Ce serait beaucoup mieux si vous disiez "une boucle de spin sera mauvaise, puisque votre le temps d'attente est long ". Dire "pause" n'aidera pas "est faux: si vous concevez mal votre programme et que vous tournez pendant très longtemps, il est toujours utile de" mettre en pause "à l'intérieur de ces boucles. En fait, c'est même * plus * important dans ce cas. (Mais encore évidemment le mauvais choix pour la synchronisation.Mieux préférable d'utiliser un spinlock pris en charge par le système d'exploitation qui peut donner le CPU et attendre un réveil si elle ne reçoit pas le verrou rapidement. Http://preshing.com/20111124/always-use-a-light-mutex/ –

+1

En outre, 'pause 'aide même sans hyperthreading: il évite un décrochage de mauvaise spécification de l'ordre de la mémoire sur la charge lors de la sortie de la boucle de spin https: // stackoverflow. com/questions/12894078/pause-instruction-in-x86 –

+0

@PeterCordes OK, je vais reformuler la réponse, je veux dire que 'EnterCriticalSection' est mieux que long loop avec un' pause'. –

Questions connexes