@Klaus:
Zitat:
....der "tatsächlichen" Frequenz. Als optimale Zeitspanne habe ich 200 ms gefunden.
Das lässt sich exakt ausrechnen. Die minimale Zeitspanne der "Zeitschleife" sollte min 2 mal so groß sein das wir alle Takte der Refrerenzfrequenz abgearbeitet haben. In unserem Falle also QueryPerformanceFrequency() * 2. Wenn diese Funktion intern auf die Time Stamp Counter geht sollte man also ca. 2 Sekunden warten, da diese Funktion ja dann die CPU Frequenz in Hz angibt und das ist auf 1 Sekunde bezogen. Der Faktor 2 erklärt sich auf Grund des Nyquist Theorems, das auch auf unseren Kalibrierungsprozess wirkt. Sollte QueryPerformanceFrequency() aber wie auf meinem P4 nur ca. 3.6MHz groß sein, die CPU aber mit 1500MHz getaktet werden , so sollte man ca. 3.6 / 1500 * 2 = 4.8 Millisekundewn lang messen. Länger macht keinen Sinn da die maximale Genauigkeit damit schon erreicht wurde.
Da wir ja mit RDTSC und QueryPerformaceCounter() in parallel messen und beide Timer unabhängig vom BIOS,
OS usw. laufen
sollten (auf SingleCPU ohne ACPI ist das noch korrekt) müssen wir uns um die Thread/Process Prioritäten, dem Tasksheduller usw. überhaupt nicht kümmern. Denn die Wartezeit im Sleep(xyz) könnnte nur größer werden aber niemals kürzer als die minimale Zeit die wir ja vorgeben. Und ansonsten benötigen wir das Sleep() ja eben nicht direkt für unsere Messung, eine Schleife mit GetTickCount() oder sonstwas anderes was minimal QueryPerformanceFrequency() *2 lang andauert hätte es auch getan.
Ergo: ob du im Sleep() 10ms oder 200ms angibts ist auf Grund der differientiellen Kalibrierungsmethode irrelevant. Wir benötigen das Sleep() ja nur damit unserer
beiden Timer eine minimale Zeitspanne von > 5ms bekommmen.
Die Prioritäten des Prozesses/Threads zu erhöhen ist Quatsch und verändert garnichts, da wir ja eben eine Differientielle Kalibrierung mit zwei vom
OS unabhängigen Timern machen.
So, aber wie es sich nun herausstellt gilt auf neuerer Hardware folgendes:
1.) RDTSC ist abhängig vom CPU Takt und dieser kann fließend und variabel in der Zeitachse durch das Power Management System ACPI einestellt werden. Gerade auf Laptops der Fall.
2.) die PerformanceCounter() benutzen selber RDTSC, sehr ungünstig für unsere Kalibrierung
3.) auf Multiprozessoren können die CPUs unterschiedliche im Takt eingestellt werden was dazu führt das die RDTSC Counter sogar asynchron zueinander sind, jeder CPU Kern hat ja einen eigenen RDTSC und auch Takt
4.) das Windows
OS benutzt in QueryPerformanceCounter() die RDTSC und während einer Messung kann die Affinitäten eines Threads zu der CPU sich ändern. Dh. dieser Thread wird teilweise auf der 1. CPU und später auf der 2. CPU ausgeführt. Das Windows
OS API für QueryPerformanceCounter() benutzt aber immer nur die RDTSC Counter der zum Aufruf der
API Funktion gültigen CPU zum Thread. Das Windows
API ist in diesem Falle also eine Fehlkonstruktion.
Ergo beides, RDTSC und QueryPerformanceCounter() sind aus ganz unterschiedlichen Gründen absolut untauglich geworden, sie sind eben nicht mehr
unabhängige Timer vom
OS/BIOS etc.pp. Eine korrekte Berechnung einer Messschleife benötigt eine Formel die gleich mindestens 3 variable Unbekannte involviert. Diese 3 Unbekannten sind auf der Zeitachse veränderlich und sind
1.) unterschiedlicher CPU Takt der einzelnen CPU Kerne, die RDTSC laufen unterschiedlich schnell
2.) QueryPerfromanceCounter() benutzt selber RDTSC, nicht mehr den Timer Chip des BIOS
3.) der Tasksheduller bzw. die Affinitäten der Threads zu verschiedenen CPUs
Diese Formel dürfte ohne klare Unterstützung der CPU, BIOS,
OS Hersteller nicht zu lösen sein. Das Microsoft das Problem auf die CPU/BIOS Hersteller abschiebt ist ebenfalls nicht korrekt.
Ich baue alle meine Routinen auf GetTickCount() um, da weis ich was ich habe. Die Lösung von MS oder BIOS muß es sein einen hochauflösenden externen Timer als
API zur Verfügung zu stellen. Dieser Timer muß eine Absolutzeit zurückgeben, denn was nützt uns eine "Zeitmessung" deren Takt sich variabel verändert ?! Das ist hirnrissig.
Gruß Hagen