web-dev-qa-db-fra.com

Comment fonctionne X86 Pause fonctionne dans Spinlock * et * peut-il être utilisé dans d'autres scénarios?

les instructions de pause sont couramment utilisées dans la boucle des tests Spinlock , lorsque un autre thread possède le spinlock, pour atténuer la boucle serrée. On dit que cela équivaut à des instructions NOP. Quelqu'un pourrait-il me dire comment cela fonctionne exactement pour l'optimisation Spinlock? Il me semble que même les instructions NOP sont un gaspillage de temps de la CPU. Vont-ils diminuer l'utilisation du processeur?

Une autre question est que puisse utiliser une instruction de pause pour d'autres fins similaires. Par exemple, j'ai un fil occupé qui continue à analyser 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 que le fil est juste en train de gaspiller le temps de la CPU. Dormez le fil et réactionnez-le par d'autres threads peut être une option, mais le fil est critique, donc je ne veux pas le faire dormir. Pour mettre en pause des instructions pour mon objectif pour atténuer l'utilisation de la CPU? Actuellement, il utilise 100% de processeur d'un noyau physique?

Merci.

39
Infinite

PAUSE Notifie la CPU selon laquelle il s'agit d'une boucle d'attente Spinlock afin que la mémoire et les accès au cache puissent être optimisées. Voir aussi Instruction de pause dans x86 Pour plus de détails sur l'évitant de la spéculation erronée de commande de la mémoire à la mémoire lorsque vous quittez la boucle de spin.

La pause peut effectivement arrêter la CPU pendant un certain temps pour économiser de l'énergie. Les processeurs plus anciens décodent comme représentant NOP. Vous n'avez donc pas à vérifier si sa prise en charge. Les centaines plus anciennes ne 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 ce soit une bonne idée d'utiliser une pause dans la vérification des file d'attente, à moins que vous ne fassiez que votre file d'attente ressemble à votre file d'attente (et qu'il n'y a pas de moyen évident de le faire).

La filature pendant très longtemps est encore très mauvaise, même avec une pause.

28
blaze

Un processeur subit une pénalité de performance grave lors de la sortie de la boucle car elle détecte une éventuelle violation de la commande de mémoire. L'instruction de pause fournit un indice au processeur que la séquence de code est une boucle de spin-attente. Le processeur utilise cette indice pour éviter la violation de la commande de mémoire dans la plupart des situations, ce qui améliore considérablement les performances du processeur. Pour cette raison, il est recommandé de placer une instruction de pause dans toutes les boucles de spin-attente. Une fonction supplémentaire de l'instruction de pause est de réduire la puissance consommée par des processeurs Intel.

[Source: Manuel Intel]

14
Nitin Kunal

Intel ne recommande que d'utiliser les instructions PAUSE lorsque la boucle de spin est très courte.

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

Vous avez écrit que vous avez un "fil qui continue à analyser certains endroits (par exemple une file d'attente) pour récupérer de nouveaux nœuds".

Dans un tel cas, Intel recommande d'utiliser des fonctions d'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 cet événement à l'aide de WaitForSingleObject(Handle, INFINITE). La file d'attente déclenchera cet événement chaque fois qu'un nouveau nœud apparaîtra.

Selon le manuel d'optimisation Intel, l'instruction PAUSE est généralement utilisée avec des threads logiciels exécutant sur deux processeurs logiques situés dans le même noyau de processeur, en attente d'une serrure à relâcher. De telles boucles d'attente courtes ont tendance à durer entre des dizaines et quelques centaines de cycles (c'est-à-dire des cycles de processeur 20-500), de sorte que la performance-sage est plus bénéfique d'attendre tout en occupant le processeur que céder au système d'exploitation.

500 cycles CPU sur un processeur 4500 MHz Core I7 7700K est de 0,0000001 secondes, c'est-à-dire 1/10000000ème d'une seconde: la CPU peut faire 10 millions de fois par seconde cette boucle de 500 cycles CPU.

Comme vous le voyez, cette instruction PAUSE est pour vraiment court périodes de temps.

D'autre part, chaque appel à une fonction API comme sommeil () éprouve le coût coûteux d'un commutateur de contexte, qui peut comporter 10000 cycles; Il subit également le coût de la bague 3 pour sonner 0 transitions, ce qui peut comporter 1000 cycles.

S'il y a plus de threads, les noyaux de processeur (multiplié à la fonction hyperthreading, si présents) sont disponibles, et un thread sera commuté à un autre au milieu d'une section critique, en attente de la section critique d'un autre thread peut vraiment prendre looong , au moins 10000 cycles, de sorte que l'instruction PAUSE sera futile.

S'il vous plaît voir ces articles 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 d'API de synchronisation OS, telles que WaitforSingleObject sur Windows OS.

En conclusion: dans votre scénario, l'instruction PAUSE ne sera pas le meilleur choix, puisque votre temps d'attente est long pendant que le PAUSE est destiné à des boucles très courtes. La pause n'est que de 131 cycles Skywell ou des processeurs ultérieurs. Par exemple, il est juste ou 31.19NS sur Intel Core I7-7700K CPU @ 4,20 GHz Kaby Lake.

Sur les processeurs antérieurs, comme Haswell, j'ai environ 9 cycles. Il est 2.81NS sur Intel Core I5-4430 @ 3GHz. Ainsi, pour les longues boucles, il est préférable de renoncer au contrôle d'autres threads à l'aide des fonctions d'API de synchronisation OS que d'occuper un processeur avec la boucle PAUSE.

2
Maxim Masiutin

L'instruction de pause semble également être utilisée dans des processeurs hyper-threading pour atténuer l'impact des performances sur d'autres fils hyper, vraisemblablement en renoncant davantage de temps de processeur.

L'article d'Intel suivant décrit cela et ne recommande pas étonnamment en évitant les boucles d'attente occupées sur ces processeurs: https://software.intel.com/en-us/articles/long-due-spin-wait-loops-on -hyper-threading-Technologie-Technologie-Technicy Processeurs

1
egbit