Frage

Ich bin Portierung, ein Spiel, das wurde ursprünglich für die Win32-API für Linux (gut, ist die Portierung von OS X-port des Win32-port auf Linux).

Ich habe umgesetzt QueryPerformanceCounter indem Sie die uSeconds seit den Prozess starten:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

Dies, gepaart mit QueryPerformanceFrequency() was eine Konstante 1000000, wie die Frequenz, die gut funktioniert auf meiner Maschine, geben Sie mir eine 64 bit variable enthält uSeconds da das Programm starten.

So ist das tragbar? Ich will nicht zu entdecken, es arbeitet sich anders, wenn der kernel kompiliert wurde, in einer bestimmten Weise oder etwas wie, dass.Ich bin gut mit, dass es nicht tragbar, um etwas anderes als Linux, aber.

War es hilfreich?

Lösung

Vielleicht.Aber Sie haben größere Probleme. gettimeofday() kann Ergebnis in falsche timings, wenn es sind Prozesse auf Ihrem system, ändern Sie den timer (ie, ntpd).Auf einem "normalen" linux, obwohl, ich glaube, die Auflösung der gettimeofday() ist 10us.Sie können springen, vorwärts und rückwärts und Zeit, folglich, auf Basis der Prozesse auf Ihrem system ausgeführt werden.Dies bewirkt die Antwort auf Ihre Frage Nein.

Sie sollten sich in clock_gettime(CLOCK_MONOTONIC) für zeitliche Intervalle.Es leidet unter einigen weniger Probleme durch Dinge wie multi-core-Systeme und externe clock-Einstellungen.

Suchen Sie auch in den clock_getres() Funktion.

Andere Tipps

Hohe Auflösung, Geringe Overhead-Timing für Intel-Prozessoren

Wenn Sie auf Intel-hardware, hier ist, wie zu Lesen Sie die CPU-Echtzeit-Unterricht Zähler.Es wird sagen Sie die Anzahl der CPU-Zyklen ausgeführt werden, da der Prozessor gebootet wurde.Dies ist wahrscheinlich der finest-grained Zähler bekommen Sie für performance-Messung.

Beachten Sie, dass die Anzahl von CPU-Zyklen.Auf linux können Sie die CPU-Geschwindigkeit von /proc/cpuinfo und dividieren, um die Anzahl der Sekunden.Konvertieren diesen zu einem Doppel ist ganz praktisch.

Wenn ich das auf meine box, ich bekomme

11867927879484732
11867927879692217
it took this long to call printf: 207485

Hier ist die Intel developer ' s guide das gibt Tonnen von Details.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}

@Bernard:

Ich muss zugeben, die meisten von deinem Beispiel ging gerade über meinem Kopf.Es tut kompilieren und zu funktionieren scheint, obwohl.Ist dies sicher für SMP-Systeme oder SpeedStep?

Das ist eine gute Frage...Ich denke, der code ist ok.Von einem praktischen Standpunkt aus, wir verwenden es in meinem Unternehmen jeden Tag, und wir laufen auf eine ziemlich Breite Palette von Boxen, alles von 2-8 Kerne.Natürlich, YMMV, etc, aber es scheint zu sein, zuverlässig und mit geringem Aufwand (weil es nicht ein context-switch in das system-space) - Methode timing.

In der Regel, wie es funktioniert, ist:

  • deklarieren Sie die block-code assembler (und volatil, so dass die optimizer wird, lassen Sie es allein).
  • führen Sie die CPUID-Anweisung.Neben einigen CPU-Informationen (was wir nicht alles tun, mit) es synchronisiert die CPU die Ausführung Puffer so, dass die timings sind nicht betroffen von der out-of-order-Ausführung.
  • führen Sie die rdtsc (read timestamp) Ausführung.Dieser holt sich die Anzahl der Maschine-Zyklen ausgeführt werden, da der Prozessor zurückgesetzt wurde.Dies ist ein 64-bit - Wert, so dass mit der aktuellen CPU-Geschwindigkeit wird es wrap-around-jedes 194 Jahren oder so.Interessant ist, dass in der ursprünglichen Pentium Referenz, beachten Sie es wickelt sich um jede 5800 Jahre oder so.
  • die letzten paar Zeilen speichern die Werte aus den Registern in die Variablen, die hi-und lo, und legte in der 64-bit-Wert zurückgeben.

Spezielle Hinweise:

  • out-of-order-Ausführung können zu falschen Ergebnissen führen, so führen wir "cpuid" - Anweisung, die zusätzlich zu geben Sie einige Informationen über die cpu synchronisiert auch alle out-of-order-Befehlsausführung.

  • Die meisten Betriebssysteme synchronisieren Sie die Schalter auf die CPUs wenn Sie anfangen, so die Antwort ist gut, innerhalb von wenigen nano-Sekunden.

  • Der ueberwinterung Kommentar ist wohl wahr, aber in der Praxis wahrscheinlich nicht kümmern timings über den Ruhezustand Grenzen.

  • bezüglich speedstep:Neuere Intel-CPUs Ausgleich für die Geschwindigkeit änderungen und kehrt mit einer bereinigten Anzahl.Ich habe einen schnellen scan über die Boxen sind in unserem Netzwerk und fand nur ein Feld, das nicht:ein Pentium 3, die einige alte Datenbank-server.(dies sind die linux-Kisten, also habe ich überprüft mit:grep constant_tsc /proc/cpuinfo)

  • Ich bin mir nicht sicher über die AMD-CPUs, wir sind in Erster Linie ein Intel-shop, obwohl ich weiß, dass einige von unseren low-level-Systeme, die gurus haben einen AMD Bewertung.

Hoffe, das befriedigt Ihre Neugier, es ist eine interessante und (IMHO) die unter-suchten Bereich der Programmierung.Sie wissen, wenn Jeff und Joel waren sprechen darüber, ob oder nicht ein Programmierer sollte wissen, C?Ich war Schreien Sie an, "hey vergessen, dass high-level-C-Zeug...assembler ist das, was Sie lernen sollten, wenn Sie wollen wissen, was der computer tun!"

Können Sie interessiert sein in Linux FAQ clock_gettime(CLOCK_REALTIME)

Wein ist eigentlich mit gettimeofday() zu implementieren, QueryPerformanceCounter() und es ist bekannt, dass viele Windows-Spiele unter Linux und Mac.

Beginnt http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

führt zu http://source.winehq.org/source/dlls/ntdll/time.c#L448

So sagt es Mikrosekunden explizit, aber sagt, die Auflösung der Systemuhr ist nicht spezifiziert.Ich nehme an, die Auflösung bedeutet in diesem Zusammenhang, wie der kleinste Betrag ist, wird es immer erhöht werden?

Die Datenstruktur ist so definiert, dass Mikrosekunden als eine Einheit der Messung, aber das bedeutet nicht, dass sich die Uhr oder das Betriebssystem in der Lage ist, das zu Messen, fein.

Wie andere Leute vorgeschlagen haben, gettimeofday() ist schlecht, weil die Einstellung der Zeit kann die Ursache clock-skew und das abwerfen Ihrer Berechnung. clock_gettime(CLOCK_MONOTONIC) ist, was Sie wollen, und clock_getres() wird sagen Sie die Präzision Ihrer Uhr.

Die tatsächliche Auflösung von gettimeofday (), hängt von der hardware-Architektur.Intel-Prozessoren als auch die SPARC-Maschinen bieten eine hohe Auflösung Timer, Messen Mikrosekunden.Andere hardware-Architekturen zurückgreifen, um den system-timer, die ist in der Regel zu 100 Hz.In solchen Fällen wird die zeitliche Auflösung wird weniger präzise.

Ich erhielt diese Antwort aus Hochauflösende Zeitmessung und Timer, Teil I

Diese Antwort erwähnt Probleme mit der Uhr nicht eingestellt.Sowohl Ihre Probleme Gewährleistung tick-Einheiten und die Probleme, die mit der Zeit angepasst werden lösen in C++11 mit dem <chrono> Bibliothek.

Die Uhr std::chrono::steady_clock garantiert nicht eingestellt werden, und darüber hinaus wird es vorab mit einer Konstanten Geschwindigkeit relativ zur Echtzeit-Technologien wie SpeedStep müssen nicht beeinflussen es.

Sie können erhalten typesafe-Einheiten durch die Umwandlung zu einer der std::chrono::duration Spezialisierungen, wie std::chrono::microseconds.Mit dieser Art es gibt keine Unklarheit über die Einheiten wird durch die tick-Wert.Jedoch, halten in Geist, dass die Uhr nicht unbedingt haben diese Auflösung.Sie können die Konvertierung einer Dauer bis attosekunden ohne tatsächlich eine Uhr, die genaue.

Von meiner Erfahrung und von dem, was ich gelesen habe, über das internet, die Antwort ist "Nein", es ist nicht garantiert.Es hängt von der CPU-Geschwindigkeit, das Betriebssystem, die Linux-Variante, etc.

Lesen Sie die RDTSC ist nicht zuverlässig in SMP-Systemen, da jede CPU pflegt Sie Ihren eigenen counter und jeder Zähler ist nicht gewährleistet, dass Sie durch die Synchronisierung mit Bezug auf eine andere CPU.

Könnte ich vorschlagen, versuchen clock_gettime(CLOCK_REALTIME).Die posix-Handbuch gibt an, dass diese umgesetzt werden sollten, auf alle kompatibel Systeme.Es kann bieten eine Nanosekunde zu zählen, aber Sie werden wahrscheinlich wollen, zu prüfen clock_getres(CLOCK_REALTIME) auf Ihrem system, um zu sehen, was die tatsächlichen Auflösung ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top