Question

Parfois, je rencontre le code qui lit TSC avec instruction rdtsc, mais les appels cpuid juste avant.

Pourquoi appelle cpuid nécessaire? Je me rends compte qu'il peut avoir quelque chose à voir avec différents noyaux ayant des valeurs de TSC, mais que exactement se produit lorsque vous appelez ces deux instructions dans l'ordre?

Était-ce utile?

La solution

Il est d'éviter hors de l'ordre d'exécution. D'un lien qui a disparu du web (mais qui a été copié fortuitement ici avant de disparaître), ce texte est un article intitulé « Suivi de la performance » par un John Eckerdal:

  

Les processeurs Pentium Pro et Pentium II prennent en charge hors de l'ordre d'exécution des instructions peuvent être exécutées dans un autre ordre que vous les programmer. Cela peut être une source d'erreurs si non pris en charge.

     

Pour éviter cela le programmeur doit sérialiser la la file d'attente instruction. Cela peut être fait par l'insertion d'une instruction de sérialisation comme instruction CPUID avant l'instruction RDTSC.

Autres conseils

Deux raisons:

  • Comme paxdiablo dit, lorsque la CPU voit un opcode CPUID il fait que toutes les instructions précédentes sont exécutées, le CPUID pris, avant toute instruction ultérieure exécuter. Sans une telle instruction, le pipeline d'exécution du processeur peut finir par exécuter TSC avant l'instruction (s) que vous souhaitez temps.
  • Une proportion importante des machines ne parviennent pas à synchroniser les registres de TSC à travers des noyaux. Vous voulez lire de a la bouche du cheval - vous assommer à http://msdn.microsoft.com/en-us/library/ee417693%28VS.85%29.aspx . Ainsi, lorsque l'on mesure un intervalle entre les lectures TSC, à moins qu'ils sont pris sur le même noyau que vous aurez une efficacité aléatoire mais peut-être constante (voir ci-dessous) intervalle introduit - il peut facilement être quelques secondes (oui secondes), même peu de temps après le démarrage . Cela reflète bien combien de temps le BIOS est en cours d'exécution sur un noyau unique avant le coup d'envoi des autres, plus - si vous avez toute option d'économie d'énergie méchant sur - la dérive croissante provoquée par des noyaux fonctionnant à des fréquences différentes ou en train de fermer à nouveau. Donc, si vous ne l'avez pas clouer les fils registres de lecture TSC au même noyau, alors vous aurez besoin de construire une sorte de table delta croix-core et de savoir l'ID de base (qui est retourné par CPUID) de chaque échantillon de TSC pour pour compenser ce décalage. C'est une autre raison pour laquelle vous pouvez voir CPUID à côté RDTSC, et même une raison pour laquelle avec RDTSCP beaucoup de systèmes d'exploitation plus récents stockent des numéros d'identification de base dans le supplément TSC_AUX [31: 0] données renvoyées. (Disponible à partir Core i7 et Athlon 64 X2, RDTSCP est une option beaucoup mieux à tous égards - le système d'exploitation vous donne normalement l'ID de base comme mentionné, atomique à la TSC lire, et empêchent réordonnancement d'instruction).

CPUID est sérialisation, empêchant exécution dans le désordre de RDTSC.

Ces jours, vous pouvez utiliser en toute sécurité LFENCE à la place. Il est documenté comme sérialisation sur le flux d'instructions (mais pas les magasins à la mémoire) sur les processeurs Intel, et maintenant aussi sur AMD après leur mise à jour du microcode pour Specter.

https: // hadibrais.wordpress.com/2018/05/14/the-significance-of-the-x86-lfence-instruction/ explique plus sur LFENCE.

Voir aussi https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark -code-exécution-paper.pdf pour un moyen d'utiliser RDTSC P qui maintient CPUID (ou LFENCE) hors de la région chronométré:

LFENCE     ; (or CPUID) Don't start the timed region until everything above has executed
RDTSC           ; EDX:EAX = timestamp
mov  ebx, eax   ; low 32 bits of start time

   code under test

RDTSCP     ; built-in one way barrier stops it from running early
LFENCE     ; (or CPUID) still use a barrier after to prevent anything weird
sub  eax, ebx   ; low 32 bits of end-start

Voir aussi Get nombre de cycles de CPU pour plus d'informations mises en garde RDTSC, comme CONSTANT_TSC et nonstop_tsc .

En prime, RDTSCP vous donne un code de base. Vous pouvez utiliser RDTSCP pour le temps de démarrage et, si vous voulez vérifier la migration de base. Mais si votre CPU possède les caractéristiques de constant_tsc, tous les cœurs dans le paquet devraient avoir leurs TSCs synchronisés de sorte que vous ne généralement pas besoin de ce x86 moderne.

Vous pouvez obtenir l'ID de base de CPUID à la place, comme @ réponse de Tony signale.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top