Entwickler-Ecke

Windows API - QueryPerformance* und Core 2 Duo


Knulli - Do 18.09.08 19:00
Titel: QueryPerformance* und Core 2 Duo
Hi Leute,

kann es sein, daß die QueryPerformance* funktionen auf einem Core 2 Duo nicht mehr richtig laufen?

Knulli


littleDave - Fr 19.09.08 16:32

QueryPerformanceCounter und QueryPerformanceFrequency sind CPU-Kern-gebunden. Das heißt, dass das Ergebniss - je nach dem welche CPU gerade dein Programm abarbeitet - unterschiedliche Werte rauskommen. Das liegt daran, dass jede CPU einen eigenen PerformanceCounter besitzt und diese bei mehreren CPUs untereinder nicht synchron sein müssen. Von AMD gibt es einen Sync-Tool, welches die Counter automatisch synchronisiert (jedoch fällt mir der Name gerade nicht ein :oops:) - bei Intel weiß ich nicht, ob es sowas gibt.

Was du auch machen könntest: du könntest den Thread, in dem du die Funktion ausführst, an eine CPU binden, dann sollte es kein Problem mehr geben.


Sinspin - Fr 19.09.08 17:15

user profile iconlittleDave hat folgendes geschrieben:
QueryPerformanceCounter und QueryPerformanceFrequency sind CPU-Kern-gebunden. Das heißt, dass das Ergebniss - je nach dem welche CPU gerade dein Programm abarbeitet - unterschiedliche Werte rauskommen.

Das ist nicht schön, ich verwende die beiden Funktionen um Animationen zu syncronisieren weil GetTickCount dafür auch nicht sonderlich gut geeignet ist.
Und jetzt darf ich sowas lesen! Da fällt mir das Wort mit dem s am Anfang ein.

Das heißt dann also soviel wie das jeder Kern einen anderen Counterwert haben kann? Wenn windows dann den Thread schön über alle Kerne verteilt bekommt man also nicht immer einen gleichmäßig ansteigenden Wert sondern hat bei einem Wechsel auf einen anderen Kern dann einen Sprung der auch mal negativ ausfallen kann?


Knulli - Fr 19.09.08 17:29

OK, Thread an CPU binden werd ich mal probieren.

Ist es 100% sicher, daß ein und derselbe Thread mal auf der einen und mal auf der anderen CPU läuft?
Ich meine damit während eines Programmlaufes. Daß es beim nächsten Start der EXE anders sein kann leuchtet mir ein, aber auch wirklich während ein und desselben Programmlaufes mal CPU#1 und mal CPU#2?

Und gibt es dann auch eine Möglichkeit herauszubekommen, auf welcher CPU mein Thread gerade läuft? Dann könnte ich ja auf die Bindung evtl. verzichten.

Hab übrigens gerade festgestellt, daß QPFrequency mal 9.18xxx und mal 9.04xxx GHz anzeigt. Wußte garnicht, daß ich so ne schnelle Kiste hab. Auf dem Prozessor steht jedenfalls 2.4 GHz...Ist aber immer nur nach einem Neustert ein anderer Wert. Solange Windows läuft, ändert er sich nicht. Mal sehen...

Knulli


Xentar - Fr 19.09.08 17:31

Ich hatte schonmal im Zusammenhang mit PC Spielen + DualCore CPU von diesem Problem gehört, dass dann manche Spiele "ruckelig" liefen, obowhl der Rechner weit über den Anforderungen liegt.
versuch mal folgendes:

In der Registry folgenden Wert eintragen:

Quelltext
1:
2:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager]
"PerfEnablePackageIdle"=dword:00000001


Und in der Boot.ini den Parameter "/usepmtimer" hinzufügen, z.B. so:

Quelltext
1:
2:
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /usepmtimer



Achtung! Ich bin mir nicht mehr sicher, ob das nur bestimmte Prozessoren betrifft.
Wenn es danach immer noch nicht besser geht, solltest du die Änderungen vielleicht wieder rückgängig machen.
Das hatte mir damals geholfen (ging um das Spiel Supreme Commander).

[Halbwissen]
Ich meine aber gehört zu haben, dass das Problem nur auftritt, wenn man NACHTRÄGLICH einen DualCore Prozessor einbaut, das Betriebssystem also schon installiert war.
[/Halbwissen]


delfiphan - Fr 19.09.08 17:40

Ich glaube nicht, dass ein Thread einer bestimmten CPU zugeordnet wird.

Wenn du 3 Threads hast, dann kriegt jede der Threads 33% der Gesamtleistung. Nicht zweimal 25% und einmal 50%. In der Taskleiste siehst du beim CPU Window ja auch nicht eine CPU 100% ausgelastet und die andere 0%, wenn ein Thread voll ausgelastet ist. Die Auslastung wird geteilt. So sieht's zu mindest aus.


Knulli - Fr 19.09.08 18:52

@Xentar
Das scheint alles nur einen AMD zu betreffen, hab zumindest beim googeln diesen Eindruck gewonnen.

@Delphifan
das hab ich jetzt auch rausbekommen, mann kann zwar sagen Prozess1 soll immer von CPU#1 oder CPU#2 bedient werden, wenn man es aber nicht tut, verteilt Windows die Last. Zumindest sieht man dieses Verhalten im Taskmanager.

@all
hab beim googeln noch mehr gefunden:
Es gibt beim Core 2 Duo noch sowas wie eine Stromsparfunktion. Wenn CPU = Langeweile dann Takt runter.
Heißt bei mir im BIOS C1E (sprich ceh-eins-eh) unter WIKI bin ich bei EIST (Enhanced Intel SpeedStep Technology) gelandet.
Ich bin natürlich immer davon ausgegangen, daß der Prozessortakt = QPFrequency ist und der QPCounter mit dieser Geschwindigkeit inkrementiert wird.
Also mal abgeschaltet und siehe da, QPFrequency zeigt 2,4 GHz an :-). Timer laufen wieder alle richtig.
Habs dann mal zur Gegenprobe wieder eingeschaltet, weil ichs den Kollegen zeigen wollte: geht trotzdem noch :-(. Auf einem Baugleichen, anderem PC gings gleich auf Anhieb richtig.
Also was das jetzt wieder war...
Hab auf jeden Fall das hier in mein Programm eingebaut:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure CheckQPFunctions();
var
  EndTicks: DWORD;
  StartQP, EndQP: Int64;
begin
  EndTicks := GetTickCount() + 500;
  StartQP  := QPJetzt();
  repeat
    EndQP := QPJetzt();
  until GetTickCount() >= EndTicks;
  if Not InRange(QPDiff(StartQP, EndQP), 0.95 * QPSec/21.05 * QPSec/2then
    ErrorMessage('Error in QueryPerformance* functions, disable EIST/C1E in BIOS!');
end;


Knulli