7 votes

Comment obtenir le nombre de cycles du processeur dans Win32 ?

Dans Win32, y a-t-il un moyen d'obtenir un compte unique de cycles du processeur ou quelque chose de similaire qui serait uniforme pour plusieurs processus/langues/systèmes/etc.

Je crée des fichiers journaux, mais je dois en produire plusieurs car nous hébergeons le runtime .NET, et j'aimerais éviter d'appeler de l'un à l'autre pour enregistrer. En tant que tel, je pensais simplement produire deux fichiers, les combiner, puis les trier, pour obtenir une chronologie cohérente impliquant des appels inter-mondes.

Cependant, GetTickCount n'augmente pas à chaque appel, donc ce n'est pas fiable. Existe-t-il un meilleur nombre, de sorte que je reçoive les appels dans le bon ordre lors du tri ?


Modifier : Merci à @Greg qui m'a mis sur la piste de QueryPerformanceCounter, qui a fait l'affaire.

12voto

prakash Points 18075

Voici un article intéressant ! dit de ne pas utiliser RDTSC, mais d'utiliser plutôt Compteur de performance des requêtes .

Conclusion :

En utilisant de vieilles timeGetTime() à faire La synchronisation n'est pas fiable sur de nombreux systèmes d'exploitation Windows Windows, car la granularité de la minuterie système peut atteindre 10-15 millisecondes, ce qui signifie que timeGetTime() n'est précis qu'à 10-15 millisecondes. (Notez que les granularités élevées se produisent sur les systèmes systèmes d'exploitation basés sur NT comme Windows NT, 2000, et XP. Windows 95 et 98 ont tendance à à avoir une bien meilleure granularité, autour de 1-5 ms.]

Cependant, si vous appelez timeBeginPeriod(1) au début de votre programme (et timeEndPeriod(1) sur la fin), timeGetTime() sera généralement devenir précis à 1 ou 2 millisecondes près, et vous fournira des informations extrêmement informations de chronométrage extrêmement précises.

Sleep() se comporte de manière similaire ; la durée de temps que Sleep() dort réellement pour va de pair avec la granularité de timeGetTime() donc après avoir appelé timeBeginPeriod(1) une fois, Sleep(1) va en fait dormir pendant 1 ou 2 millisecondes, Sleep(2) pour 2-3, et ainsi (au lieu de dormir par incréments aussi élevés que 10-15 ms).

Pour un chronométrage plus précis (précision de l'ordre de la milliseconde), vous probablement éviter d'utiliser la fonction mnémonique d'assemblage RDTSC car il est difficile à calibrer ; à la place, utilisez QueryPerformanceFrequency et QueryPerformanceCounter qui sont précises à moins de 10 microsecondes (0,00001 seconde).

Pour le chronométrage simple, les deux timeGetTime et QueryPerformanceCounter fonctionnent bien, et QueryPerformanceCounter est évidemment plus précis. Cependant, si vous avez besoin d'effectuer des "pauses pauses temporisées" (comme celles nécessaires pour la limitation du framerate), vous devez faire attention à ne pas rester dans une boucle à appeler QueryPerformanceCounter, en attendant qu'il atteigne une certaine valeur. qu'il atteigne une certaine valeur ; cela Cela consommera 100 % de votre processeur. Envisagez plutôt un schéma hybride où vous appelez Sleep(1) (sans oublier timeBeginPeriod(1) en premier !) chaque fois que vous avez besoin de passer plus de 1 ms de temps, et n'entrez alors que le boucle 100% occupée de QueryPerformanceCounter que pour terminer le dernier < 1/1000ème de seconde seconde du délai dont vous avez besoin. Ce site vous donnera des délais ultra-précis (précis à 10 microsecondes), avec une utilisation une utilisation minimale du CPU. Voir le code ci-dessus.

9voto

Greg Hewgill Points 356191

Vous pouvez utiliser le RDTSC Instruction du CPU (en supposant qu'il s'agisse de x86). Cette instruction donne le compteur de cycles du CPU, mais sachez qu'il augmentera très rapidement jusqu'à sa valeur maximale, puis sera remis à 0. Comme le mentionne l'article de Wikipedia, il serait préférable d'utiliser l'instruction Compteur de performance des requêtes fonction.

2voto

Troybolo Points 1

System.Diagnostics.Stopwatch.GetTimestamp() renvoie le nombre de cycle du CPU depuis un moment donné (peut-être au démarrage de l'ordinateur, mais je ne suis pas sûr) et je n'ai jamais vu qu'il n'augmentait pas entre 2 appels.

Les cycles CPU seront spécifiques à chaque ordinateur. Vous ne pouvez donc pas l'utiliser pour fusionner les fichiers journaux entre deux ordinateurs.

2voto

moonshadow Points 28302

La sortie du RDTSC peut dépendre de la fréquence d'horloge du cœur actuel, qui, pour les processeurs modernes, n'est ni constante ni, dans une machine multicœur, cohérente.

Utilisez l'heure du système, et si vous traitez des flux provenant de plusieurs systèmes, utilisez une source de temps NTP. Vous pouvez obtenir des relevés de temps fiables et cohérents de cette manière ; si les frais généraux sont trop élevés pour vos besoins, l'utilisation de la source de temps NTP peut s'avérer utile. HPET pour calculer le temps écoulé depuis la dernière lecture fiable connue de l'heure est préférable à l'utilisation du HPET seul.

1voto

Ken Points 1693

Utilisez le GetTickCount et ajoutez un autre compteur au fur et à mesure que vous fusionnez les fichiers journaux. Vous n'obtiendrez pas une séquence parfaite entre les différents fichiers journaux, mais cela permettra au moins de conserver tous les journaux de chaque fichier dans le bon ordre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X