Comment fonctionne l'instruction pause x86 dans spinlock *et* peut-elle être utilisée dans d'autres scénarios?
instruction de pause est couramment utilisé dans la boucle de test spinlock , quand un autre fil possède le spinlock, pour atténuer la boucle serrée. On dit que c'est l'équivalent de quelques instructions NOP. Quelqu'un pourrait me dire exactement comment il fonctionne pour spinlock optimisation? Il me semble que même les instructions NOP sont une perte de temps CPU. Seront-ils baisse d'utilisation de l'UC?
une autre question Est Que pourrais-je utiliser l'instruction pause pour à d'autres fins semblables. Par exemple, j'ai un thread occupé qui continue à scanner certains endroits (par exemple une file d'attente) pour récupérer de nouveaux noeuds; cependant, parfois la file d'attente est vide et le thread est en train de perdre du temps cpu. sommeil le fil et de le réveiller par d'autres threads peuvent être une option, mais le fil est essentielle, c'est pourquoi je ne veux pas le faire dormir. Est-ce que l'instruction pause pourrait fonctionner dans le but d'atténuer l'utilisation du CPU? Actuellement, il utilise 100% cpu d'un noyau physique?
Merci.
4 réponses
PAUSE " informe le CPU qu'il s'agit d'une boucle d'attente spinlock afin d'optimiser les accès mémoire et cache. Voir aussi pause instruction dans x86 pour plus de détails sur la façon d'éviter les fausses spéculations de l'ordre de la mémoire en quittant la boucle de spin.
PAUSE peut en fait arrêter CPU pendant un certain temps pour économiser de l'énergie. Les CPU plus anciens le décodent comme REP NOP, donc vous n'avez pas à vérifier si son support est pris en charge. Les CPU plus âgés feront tout 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 c'est une bonne idée d'utiliser une PAUSE dans la file d'attente de la vérification, à moins que vous allez faire de votre file d'attente de spinlock-like (et il n'est pas évident de trouver un moyen de le faire).
tourner pendant très longtemps est encore très mauvais, même avec PAUSE.
un processeur subit une sévère pénalité de performance lors de la sortie la boucle parce qu'elle détecte une possible violation de l'ordre de mémoire. La PAUSE d'instruction fournit une indication au processeur que la séquence de code est une boucle de spin-wait. Le le processeur utilise cette indication pour éviter la violation de l'ordre de mémoire dans la plupart des situations, ce qui améliore considérablement les performances du processeur. Pour cette raison, il est recommandé qu'une instruction PAUSE soit placée dans toutes les boucles spin-wait. Une fonction supplémentaire de la PAUSE l'instruction est de réduire la puissance consommée par les processeurs Intel.
[source: manuel Intel]
L'instruction PAUSE semble également être utilisée dans les processeurs à filetage hyper pour atténuer l'impact de la performance sur les autres fils hyper, probablement en leur laissant plus de temps CPU.
L'article suivant D'Intel le souligne, et recommande sans surprise d'éviter les boucles d'attente sur de tels processeurs: https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
Intel ne recommande d'utiliser les instructions PAUSE
que lorsque la boucle de spin est très courte.
comme j'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 à scanner certains endroits (par exemple une file d'attente) pour récupérer de nouveaux noeuds".
dans ce cas, Intel recommande d'utiliser les fonctions API de synchronisation de votre le système d'exploitation. Par exemple, vous pouvez créer un événement quand un nouveau noeud apparaît dans une file d'attente, et juste attendre cet événement en utilisant le WaitForSingleObject(Handle, INFINITE)
. La file d'attente déclenchera cet événement chaque fois qu'un nouveau noeud apparaîtra.
selon le manuel D'optimisation Intel, l'instruction PAUSE
est typiquement utilisée avec des threads logiciels exécutés sur deux processeurs logiques situés dans le même noyau de processeur, en attente de libération d'une serrure. De telles petites boucles d'attente ont tendance à durer. entre des dizaines et quelques centaines de cycles (i.e. 20-500 cycles CPU), il est donc plus avantageux d'attendre en occupant le CPU que de céder à L'OS.
500 cycles CPU sur un processeur 4500 MHz Core i7 7700K est 0,0000001 secondes, soit 1 / 10000000th of a second: le CPU peut faire 10 millions de fois par seconde cette boucle CPU 500 cycles.
comme vous le voyez, cette instruction PAUSE
est pour vraiment courtes périodes de temps.
d'un autre côté, chaque appel à une fonction API comme Sleep() fait l'expérience du coût coûteux d'un commutateur de contexte, qui peut être 10000+ cycles; il souffre également le coût de l'anneau 3 à ring 0 transitions, qui peuvent être 1000+ cycles.
S'il y a plus de threads, alors les noyaux du processeur (multipliés par la fonction hyperthreading, si présent) sont disponibles, et un thread sera commuté à un autre au milieu d'une section critique, en attente pour la section critique d'un autre fil peut vraiment prendre looong , au moins 10000+ cycles, de sorte que l'instruction PAUSE
sera futile.
s'il vous Plaît voir cet article pour plus d'informations:
- https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors
- https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
lorsque la boucle d'attente est censée durer des milliers de cycles ou plus, elle est il est préférable de céder au système d'exploitation en appelant l'une des fonctions de l'API de synchronisation OS, comme WaitForSingleObject sur Windows OS.
comme une conclusion: dans votre scénario, l'instruction PAUSE
ne sera pas le meilleur choix, puisque votre le temps d'attente est long alors que le PAUSE
est destiné à des boucles très courtes. PAUSE est seulement 131 cycles SkyWell ou des processeurs plus récents. Par exemple, il est juste ou 31.19 ns sur Intel Core i7-7700K CPU @ 4.20 GHz Kaby Lake.
sur les premiers processeurs, comme Haswell, j'ai environ 9 cycles. C'est 2,81 ns sur Intel Core i5-4430 @ 3GHz. Ainsi, pour les boucles longues, il est préférable de céder le contrôle à d'autres threads en utilisant les fonctions de l'API de synchronisation OS que d'occuper le CPU avec le PAUSE
en boucle.