Wie erhalte ich die CPU-Zykluszahl in Win32?

7

In Win32 gibt es eine Möglichkeit, eine eindeutige CPU-Zykluszahl oder Ähnliches zu erhalten, die für mehrere Prozesse / Sprachen / Systeme / etc. einheitlich ist.

Ich erstelle einige Protokolldateien, muss aber mehrere Protokolldateien erstellen, weil wir die .NET-Laufzeitumgebung hosten, und ich möchte es vermeiden, von einem zum anderen Protokoll aufzurufen. Daher dachte ich, ich würde einfach zwei Dateien erzeugen, sie kombinieren und sie dann sortieren, um eine kohärente Zeitleiste zu erhalten, die weltübergreifende Anrufe beinhaltet.

GetTickCount erhöht sich jedoch nicht bei jedem Anruf, daher ist das nicht zuverlässig. Gibt es eine bessere Nummer, damit ich beim Sortieren die Anrufe in der richtigen Reihenfolge bekomme?

Bearbeiten : Dank @Greg habe ich mich auf den Weg zu QueryPerformanceCounter gemacht , die den Trick gemacht haben.

    
Lasse Vågsæther Karlsen 26.09.2008, 11:44
quelle

5 Antworten

8

Sie können die RDTSC CPU-Anweisung verwenden (vorausgesetzt, x86). Diese Anweisung gibt den CPU-Zyklus-Zähler, aber beachten Sie, dass es sehr schnell auf seinen maximalen Wert erhöht und dann auf 0 zurückgesetzt wird. Wie der Wikipedia-Artikel erwähnt, ist es besser, die QueryPerformanceCounter Funktion.

    
Greg Hewgill 26.09.2008, 11:48
quelle
12

Hier ist ein interessanter Artikel! sagt, dass Sie nicht RDTSC verwenden sollen, sondern stattdessen QueryPerformanceCounter .

Fazit:

  

Benutze reguläres altes timeGetTime() zu tun   Timing ist bei vielen nicht zuverlässig   Windows-basierte Betriebssysteme   weil die Granularität des Systems   Timer kann so hoch wie 10-15 sein   Millisekunden, das bedeutet    timeGetTime() ist nur korrekt   10-15 Millisekunden. [Notiere dass der   hohe Granularitäten treten auf NT-Basis auf   Betriebssysteme wie Windows NT,   2000 und XP. Windows 95 und 98 neigen dazu   um eine viel bessere Granularität zu haben,   etwa 1-5 ms.]

     

Allerdings, wenn Sie anrufen    timeBeginPeriod(1) am Anfang von   Ihr Programm (und timeEndPeriod(1) at   das Ende), timeGetTime() wird normalerweise   werden auf 1-2 Millisekunden genau,   und wird dich extrem versorgen   genaue Timing-Informationen.

     

Sleep() verhält sich ähnlich; die Länge   von Zeit, die Sleep() tatsächlich schläft   denn geht Hand in Hand mit dem   Granularität von timeGetTime() , also nach   ruft timeBeginPeriod(1) einmal auf,    Sleep(1) wird tatsächlich für 1-2 schlafen   Millisekunden, Sleep(2) für 2-3 und so   auf (anstatt in Schritten zu schlafen   so hoch wie 10-15 ms).

     

Für ein präziseres Timing   (Genauigkeit im Millisekundenbereich), werden Sie   wahrscheinlich vermeiden wollen, die   Assembly Mnemonic RDTSC, weil es ist   schwer zu kalibrieren ; stattdessen verwenden    QueryPerformanceFrequency und    QueryPerformanceCounter , das sind   genau auf weniger als 10 Mikrosekunden   (0,00001 Sekunden).

     

Für einfaches Timing, sowohl timeGetTime   und QueryPerformanceCounter funktionieren gut,   und QueryPerformanceCounter ist   offensichtlich genauer. Wie auch immer, wenn   Sie müssen jede Art von "zeitlich abgestimmt" tun   Pausen "(wie die für   Bildfrequenzbegrenzung), müssen Sie sein   vorsichtig, in einer Schleife zu sitzen, die ruft   QueryPerformanceCounter, wartet auf   um einen bestimmten Wert zu erreichen; dieser Wille   verschlinge 100% deines Prozessors.   Betrachten Sie stattdessen ein hybrides Schema,   wo du Schlaf nennst (1) (vergiss nicht   timeBeginPeriod (1) zuerst!) wann immer   Sie müssen mehr als 1 ms von übergeben werden   Zeit, und geben Sie dann nur die   QueryPerformanceCounter 100% -Busy-Schleife   um das letzte & lt; 1/1000 eines   Sekunde der Verzögerung, die Sie brauchen. Dies   gibt Ihnen ultra-genaue Verzögerungen   (genau bis 10 Mikrosekunden), mit   sehr geringe CPU-Auslastung. Siehe den Code   oben.

    
prakash 26.09.2008 11:52
quelle
2

System.Diagnostics.Stopwatch.GetTimestamp () gibt die Anzahl der CPU-Zyklus seit einem Zeitpunkt der Herkunft (vielleicht, wenn der Computer gestartet, aber ich bin mir nicht sicher) und ich habe noch nie gesehen, es nicht zwischen 2 Anrufe erhöht.

Die CPU-Zyklen sind für jeden Computer spezifisch, so dass Sie die Protokolldatei nicht zwischen zwei Computern zusammenführen können.

    
Seb 26.09.2008 11:54
quelle
2

Die RDTSC-Ausgabe kann von der Taktfrequenz des aktuellen Kerns abhängen, die für moderne CPUs weder konstant noch in einer Mehrkernmaschine konsistent ist.

Verwenden Sie die Systemzeit, und wenn Sie Feeds von mehreren Systemen verwenden, verwenden Sie eine NTP-Zeitquelle. Sie können auf diese Weise zuverlässige, konsistente Zeitwerte erhalten; Wenn der Overhead für Ihre Zwecke zu hoch ist, verwenden Sie HPET , um die Zeit zu berechnen, die seit der letzten bekannten zuverlässigen Zeitmessung verstrichen ist besser als die HPET allein.

    
moonshadow 26.09.2008 11:57
quelle
1

Verwenden Sie GetTickCount und fügen Sie beim Zusammenführen der Protokolldateien einen weiteren Zähler hinzu. Gibt Ihnen keine perfekte Reihenfolge zwischen den verschiedenen Protokolldateien, aber es wird mindestens alle Protokolle aus jeder Datei in der richtigen Reihenfolge behalten.

    
Ken 26.09.2008 11:53
quelle

Tags und Links