AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi exakte Zeitmessungen auf Multiprozessoren
Thema durchsuchen
Ansicht
Themen-Optionen

exakte Zeitmessungen auf Multiprozessoren

Ein Thema von negaH · begonnen am 29. Sep 2006 · letzter Beitrag vom 19. Jul 2011
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#1

exakte Zeitmessungen auf Multiprozessoren

  Alt 29. Sep 2006, 21:44
Hi Leute,

heute musste ich erstaunt feststellen das meine Zeitmessroutinen/Taktanzahlmessungen auf einem Intel Duo Core Laptop total falsche Ergebnisse liefern. Ich hatte mich schon damit abgefunden das zb. meine Pi Berechnungen auf einem Core Duo 2.16Ghz Laptop nur 4 mal schneller sind als auf einem P4 1.5Ghz Rechner. Das heist das mein Laptop nur 4 mal schneller ist und nicht mehr Power hergibt.

Jetzt musste ich aber feststellen das es garnicht an dem ist, sondern das meine Zeitmessungen falsche Ergebnisse liefert. Es scheint nun wohl so zu sein das auf dem Laptop die Berechnungen ca. 12 mal schneller sind, was mich natürlich freut, da ich nun einen Rechner habe der innerhalb der letzten Stunde drastisch schneller geworden ist

Ok. Meine Messroutinen arbeiten mit dem Real Time Counter -> RDTSC. Um dessen Werte in Zeiten umrechnen zu können messe ich mit QueryPerformanceCounter()/Frequency() quasi die Taktfrequenz der CPU aus. RDTSC liefert ja nur die CPU Takte zurück und zb. keine Millisekunden.

Nun, das Ausrechnen dieser Taktfrequenz scheint wohl auf Multiprozessoren nicht ganz trivial zu sein. Besonders weil ja auf Laptops zusätzlich noch das ACPI dazwischen funkt und den Prozessortakt variabel einstellen kann.

Gut, ich weis das man mit GetTickCount() auf der sicheren Seite ist, allerdings ist dessen Auflösung eben nicht berauschend. Ich würde also ungern auf RDTSC verzichten, benötige dann aber auch eine exakte Umrechnung von RDTSC in Zeit.

Hat einer von euch eine Idee, Source oder Hinweise wo ich suchen könnte ?
Und als zweite Frage: kann es sein das das ACPI beide Prozessoren unterschiedlich in der Taktfrequenz drosseln kann ?

Gruß Hagen
  Mit Zitat antworten Zitat
supermuckl

Registriert seit: 1. Feb 2003
1.340 Beiträge
 
FreePascal / Lazarus
 
#2

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 29. Sep 2006, 22:19
ich hab das gleiche problem mit dem queryperformancecounter dingens.
meine zeitberechnung zeigt teilweise sogar negative werte an, wenn ich die zeit zwischen 2 befehlen messen will, die dort vergangen ist!!

ich bin mit meinem latein am ende.

gettickcount ist mir auch zu ungenau
und der dx-timer zu ressourcenintensiv
Das echte Leben ist was für Leute...
... die im Internet keine Freunde finden!
  Mit Zitat antworten Zitat
Benutzerbild von St.Pauli
St.Pauli

Registriert seit: 26. Dez 2004
351 Beiträge
 
Delphi 7 Personal
 
#3

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 29. Sep 2006, 22:28
Das scheint nicht nur dir so zu gehen. Das Problem müssen auch viele andere Programme (z.B. Spiele) haben die QueryPerformanceCounter und QueryPerformanceFrequency verwenden.

Zitat von Microsoft:
While the QueryPerformanceCounter / QueryPerformanceFrequency API is intended to be multiprocessor aware, bugs in the BIOS or motherboard drivers may result in these routines returning different values as the thread moves from one processor to another.
http://www.gamedev.net/community/for...opic_id=409541

http://support.microsoft.com/kb/909944

Ein AMD-Schreiben

Was ich herausgelesen habe ist, dass es auch helfen kann wenn man die neusten Treiber von AMD oder Intel installieren sollte.
Gruß St.Pauli
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#4

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 29. Sep 2006, 23:14
Das grunglegende Problem ist der mehrfache Taskswitch pro Sekunde und dein Task wird auch frei von einem Kern auf den anderen verschoben. Wenn ein Kern mal öfters im Halt war oder mehrfach die Taktfrequenz änderte, dann gehen die Time Stamp Counter der beiden Kerne auseinander, da einer weniger Taktimpulse hatte als der andere. Da nun der Thread/Prozess mehrfach zwischen den Kernen wechselt, ist die wahrscheinlich hoch, dass man auf einem Kern den Counter liest (Startpunkt) und auf einem/dem anderen Kern den Counter beim Stoppen. Und so einfach kann die Zeit auch mal negativ sein.

Abhilfe würde hier z.B. das Festlegen eines Threads/Prozesses auf einen logische CPU/Kern helfen. Dies schliesst das beschriebene aus, aber nicht die Nebenwirkungen des Power/Taktmanagements.

SetThreadAffinityMask(), SetProcessAffinityMask(), etc ...

So, Details und weitere Info's in den über mir verlinkten Links..
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#5

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 29. Sep 2006, 23:17
Naja, das ist nicht so trivial wie es sich anhört.

Ich messe ja nicht mit QueryPerformanceCounter() sondern die CPU Takte mit RDTSC -> Time Stamp Counter.

Das sieht dann ungefähr so aus:

1.) Kalibration

- ermittelle die RDTSC Takte für eine beliebige Zeitdauer X (zb. 10ms)
- ermittelle parallel dazu mit QueryPerrformanceCounter() einen Start und Stop Wert
- man hat nun 2 Differenzwerte: 1.) Anzahl der CPU Takte der Messschleife und 2. Anzhal der Takte relativ zu PerformanceFrequency()
- am Schluß kann man mit RDTSC_Takte / Performance_Takte * Peormance_Frequency also die Taktfrequenz der CPU ermitteln.
- dieser Wert wird global gespeichert

2.) Messung

- lese Time Stamp Counter mit RDTSC
- führe zu messende Funktionen aus
- lese Time Stamp Counter mit RDTSC und bilde Differenz, also die Anzhal der CPU Takte der ausgemessenen Funktion

3.) Umrechnung
- dividiere obige errechnete CPU_Frequency durch RDTSC_Takt_Anzhal_gemessen und je nach gewünschter Zeitskale multpliziere es zb. mit 1000 um Millisekunden zu haben

Dh. alle meine Messungen messen nur die CPU Takte aus und rechnen das am Schluß erst auf Zeit um.

Wenn aber die Taktfrequenz einer CPU nicht mehr konstant ist, also variabel mit der Zeit durch das ACPI angepasst werden kann, dann gibt es keinen Weg irgendwelche genaue Messungen durchzuführen, zumnindestens mit dem Time Stamp Counter.

Schätze mal das GetTickCount() wirklich die einzigste Alternative ist, der Time Stamp Counter ist auf alle Fälle unbrauchbar geworden.

Gruß Hagen
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.058 Beiträge
 
Delphi XE2 Professional
 
#6

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 30. Sep 2006, 02:03
Hallo Hagen,

ich benutze zum Zeitmessen auch nur RDTSC, und die Kalibrierung mache ich auch so wie Du.
Allerdings habe ich bemerkt, daß bei sehr kurzen Kalibrierungszeiten (Du erwähntest 10 ms) die Ergebnisse (RDTSC-Ticks/Sekunde) weit weg waren von der "tatsächlichen" Frequenz. Als optimale Zeitspanne habe ich 200 ms gefunden.

Delphi-Quellcode:
FUNCTION TimeStamp:Int64;
asm
   rdtsc
end;

FUNCTION TimeStampFrequency:int64;
var oldpriority:word; q0,q1,qf,ts0,ts1:int64; seconds:extended;
begin
   oldpriority:=GetThreadPriority(GetCurrentThread);
   SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);
   QueryPerformanceCounter(q0);
   ts0:=TimeStamp;
   Sleep(200);
   ts1:=TimeStamp;
   QueryPerformanceCounter(q1);
   SetThreadPriority(GetCurrentThread,oldpriority);
   QueryPerformanceFrequency(qf);
   seconds:=(q1-q0)/qf;
   result:=Trunc((ts1-ts0)/seconds+0.5);
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#7

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 30. Sep 2006, 10:26
Hallo Hagen,

es gibt einen interessanten Artikel von Chuck Walbourn im MSDN zu diesem Thema: Game Timing and Multicore Processors.

Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#8

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 30. Sep 2006, 12:17
@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
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#9

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 30. Sep 2006, 12:31
Es ergeben sich aber auch andere Vorteile bzw. Möglichkeiten

Man kann RDTSC dazu benutzten um die RMS Auslastung der CPUs zu messen. Auf meinem Laptop zb. ergaben sich für die gleiche zu messende Funktion folgende Zeiten

1.) 12 sec
2.) 4 sec

Das zeigt uns das die 2. Messung auf einer CPU lief die 3 mal schneller getaktet wurde als bei der 1. Messung. Man könnte also eine TrayIcon APP bauen die für jede CPU die aktuelle Taktfrequenz anzeigt. Nun kann man dies PI*Daumen umrechnen in Stromverbrauch, denn bei CMOS ist es so das quasi nur die Taktfrequenz die Stromaufnahme bestimmt.

Gruß Hagen

PS: Marabu, danke für den Link, ich hätte mir mein Palaver oben sparen könne
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#10

Re: exakte Zeitmessungen auf Multiprozessoren

  Alt 30. Sep 2006, 18:09
Wenn du keine Gleitkomma-Ops benutzt, kannste deine Berechnung ja in den Kernelmode verlegen und bei gehaltenem Spinlock (nicht auf Checked Versions machen ) tätigen. Das System reagiert dann zwar solange nicht mehr, bis die Berechnung fertig ist und sie läuft auch nur auf einer CPU, aber ansonsten ist alles fit. Ach ja ... wenn du den FPU-Status vorher sicherst, kannste natürlich auch mit FPU-Ops "rummachen"
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz