AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Taktfrequenz berechnen, Realtime Counter, Überlauf ?
Thema durchsuchen
Ansicht
Themen-Optionen

Taktfrequenz berechnen, Realtime Counter, Überlauf ?

Ein Thema von El.Blindo · begonnen am 27. Jan 2008 · letzter Beitrag vom 28. Jan 2008
Antwort Antwort
El.Blindo

Registriert seit: 24. Okt 2006
18 Beiträge
 
#1

Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 27. Jan 2008, 14:25
Moin erstmal,

Ich bin ja schon eine Weile hier angemeldet, und habe mir auch schon die eine oder andere "Anregung" hier geholt.
Die meisten meiner kleinen Probleme haben sich bisher durch aufmerksames Lesen von Foren-Beiträgen gelöst.

Nun stehe ich allerdings vor einem Problem, bei dem ich nicht weiter komme.

Zur Erläuterung:

Sinn der Sache ist es auf Core 2 Prozessoren die aktuelle Taktfrequenz zu berechnen, ohne eine nennenswerte CPU-Last zu erzeugen. Verwendet wird hier Winring0 eine OpenSys Library.
Wie vielleicht bekannt ist konnte auf "älteren" Prozessoren die Taktfrequenz alleine über den Realtime Counter, sowie über den Performance Counter bestimmt werden.
Neuere Prozessoren, so auch der Core 2, haben einen konstanten TSC (Constant_TSC), d.h. unabhängig von der aktuellen Taktfrequenz wird der Realtime Counter mit der nominellen Taktfrequenz betrieben.

Ich habe mich in den letzten Tagen eingehend mit Intel Datenblättern und verschiedenen Counterwerten beschäftigt und bin zu dem Code der hier einfügt ist gekommen.

Verwendet werden hier zusätzlich IA32_APERF_MSR und IA32_MPERF_MSR.

IA32_APERF_MSR gibt die Anzahl der Taktzyklen wieder die sich der Prozessor im C0 State befand, bezogen auf die aktuelle Taktfrequenz.

IA32_MPERF_MSR gibt die Anzahl der Taktzyklen wieder die sich der Prozessor im C0 State befand, bezogen auf die nominelle Taktfrequenz.

Nun zum Problem: T_Delta wird in meinem Code als DWord deklariert, richtig wäre eigentlich Int64. Wenn ich T_Delta jedoch als Int64 deklariere treten bei der Berechnung der Taktfrequenz negative Werte auf.
Scheinbar gibt es Probleme damit das Int64 ein signed Wert ist, die Ausgabe des Realtime Counters jedoch ein unsigned Wert.

Hat jemand eine Idee wie dieses Problem zu lösen ist ?

Ich hänge sicherheitshalber noch einmal das gesamte Projekt an.


Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  EAX, EDX : DWord; //Variablen für Register Übergabe
  Frequency : Int64; //Performance Counter Frequency
  P_Count : Int64; //Performance Counter aktueller Wert
  A_Count : Int64; //IA32_APERF_MSR Aktueller Wert
  M_Count : Int64; //IA32_MPERF_MSR Aktueller Wert
  T_Count : Int64; //Realtime Counter Aktueller Wert
  P_Delta : Int64; //Performance Counter Delta Wert
  A_Delta : Int64; //IA32_APERF_MSR Delta Wert
  M_Delta : Int64; //IA32_MPERF_MSR Delta Wert
  T_Delta : DWord; //Sollte eigentlich auch Int64 sein !!!
  PC,PT : Cardinal;
  Nominal : Integer;
  Aktuell : Integer;
begin
  // Routine läuft nur auf Core1
  SetThreadAffinityMaskByID(GetCurrentThreadID, 1);
  // Sichern der alten Prioritäten
  PC := GetPriorityClass(GetCurrentProcess);
  PT := GetThreadPriority(GetCurrentThread);
  // Höchste Priorität
  SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
  SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
  // Performance Counter und Frequenz abfragen und merken
  QueryPerformanceFrequency(Frequency);
  QueryPerformanceCounter(P_Count);
  // Realtime Counter abfragen und merken
  Rdtsc(EAX,EDX);
  T_Count := EAX + EDX shl 16;
  // IA32_APERF_MSR abfragen und merken
  Rdmsr(IA32_APERF_MSR,EAX,EDX);
  A_Count := EAX + EDX shl 16;
  // IA32_MPERF_MSR abfragen und merken
  Rdmsr(IA32_MPERF_MSR,EAX,EDX);
  M_Count := EAX + EDX shl 16;
  //Warten ohne CPU-Last, die genauigkeit steigt mit steigender Wartezeit
  Sleep(250);
  // Performance Counter und Delta berechnen
  QueryPerformanceCounter(P_Delta);
  P_Delta := P_Delta-P_Count;
  // Realtime Counter abfragen und Delta berechnen
  Rdtsc(EAX,EDX);
  T_Delta := (EAX + EDX shl 16) - T_Count;
  // IA32_APERF_MSR abfragen und Delta berechnen
  Rdmsr(IA32_APERF_MSR,EAX,EDX);
  A_Delta := (EAX + EDX shl 16) - A_Count;
  // IA32_MPERF_MSR abfragen und Delta berechnen
  Rdmsr(IA32_MPERF_MSR,EAX,EDX);
  M_Delta := (EAX + EDX shl 16) - M_Count;
  // Berechnung der nominellen Taktfrequenz (Constant_TSC)
  Nominal := Round(T_Delta/(P_Delta/Frequency)/1000000);
  // Berechnung der aktuellen Taktfrequenz
  Aktuell := Round(Nominal*(A_Delta/M_Delta)+0.5);
  // Alte Prioritäten wiederherstellen
  SetThreadPriority(GetCurrentThread, PT);
  SetPriorityClass(GetCurrentProcess, PC);
  Memo1.Lines.Add('Nomineller Prozessortakt : '+ IntToStr(Nominal));
  Memo1.Lines.Add('Aktueller Prozessortakt : '+ IntToStr(Aktuell));
  Memo1.Lines.Add('');
end;
MfG

El.Blindo
Angehängte Dateien
Dateityp: zip perfmsr_541.zip (43,8 KB, 16x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.168 Beiträge
 
Delphi 12 Athens
 
#2

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 27. Jan 2008, 21:58
Zitat:
Scheinbar gibt es Probleme damit das Int64 ein signed Wert ist, die Ausgabe des Realtime Counters jedoch ein unsigned Wert.
UInt64? (unsigned Int64)


[add]
statt Addition
EAX + EDX shl 16 eine nette Verknüpfung
EAX or EDX shl 16; ist etwas schneller/optimaler
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
El.Blindo

Registriert seit: 24. Okt 2006
18 Beiträge
 
#3

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 01:12
Danke für den Tip mit dem OR.

Allerdings bin ich jetzt noch mehr verwirrt. Naja, ist schon Spät.
Ich werde morgen mal ein paar Ausgaben mehr ins Memo bauen, dann sieht man was ich meine.
Erstaunlicherweise erzeugt der Realtime Counter negative Werte, confused.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.168 Beiträge
 
Delphi 12 Athens
 
#4

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 01:18
!!! an alle Tester: bei mir hat diese Ring0.dll einen netten BlueScreen ausgelöst
also sollte ihr vorher besser mal alles Speichern
> AMD Duron
(wollt nur mal sehn was der hier anzeigt )


also wenn es nur an dem "signed" liegt, dann einfach statt Int64 dieses knuffige UInt64 verwenden.

UInt64 ist praktisch ein 64-Bit-DWord und kennt somit kein Negativ


Bist du mit dem shl 16 eigentlich sicher?
(ist mir garnicht aufgefallen, aber wenn das stimmt, dann nimm doch besser + )
außerdem solltest du für das SHL den Datentyp vorher vergrößern, da sonst die höheren "16" Bits ins nirgendwo gescoben werden, da zu diesem Zeitpunkt EDX noch ein DWord ist ... wärend der Berechnung ist/bleibt er noch DWord und wird erst bei der Zuweisung an den (U)Int64 in diesesn Typen umgewandelt ... also SHL wird noch auf ein DWord angewendet.
Angehängte Dateien
Dateityp: pas main_305.pas (5,7 KB, 5x aufgerufen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 07:36
  T_Count := EAX + EDX shl 16; richtiger wäre

Delphi-Quellcode:
  
  UInt64Rec(T_Count).Lo := EAX;
  UInt64Rec(T_Count).Hi := EDX;
// oder
  T_Count := EAX + EDX shl 32;
// falls Delphi EDX automatisch auf 64Bit Datentyp erweitert, ansonsten EDX vorher in einen temporären UInt64 kopieren
Gruß hagen
  Mit Zitat antworten Zitat
El.Blindo

Registriert seit: 24. Okt 2006
18 Beiträge
 
#6

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 08:37
Sorry Doppelpost
  Mit Zitat antworten Zitat
El.Blindo

Registriert seit: 24. Okt 2006
18 Beiträge
 
#7

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 09:30
Erstmal, Sorry für den Bluescreen. Ist halt für Core Prozessoren.

Wobei, verstehen kann ich auch das nicht. Das Programm prüft erst ob die CPUID unterstützt wird, wenn nicht bricht es ab.
Wenn CPUID unterstützt wird, dann wird auf den Vendor geprüft, ist dieser nicht GENUEINTEL wird das Programm abgebrochen.
Beim AMD Duron sollte dort eigentlich AUTENTICAMD stehen.

Vielleicht liegt es am statischen Einbinden der DLL, wobei, das sollte eigentlich auch nix machen, das vor der Überprüfung auf den Prozzessor keine DLL Aufrufe erfolgen.

Wie dem auch sei, ich habe, um der Sache auf den Grund zu kommen:

1. Eure Tips beachtet, shl 32 müsste übrigens richtig sein, was bin ich für ein Depp.
2. Ich habe die Ausgaben im Memo erweitert.
3. Nun funktioniert es.

Ich habe nun folgendes gemacht:

Delphi-Quellcode:

type
  UInt64 = packed record
    Lo, Hi : DWord;
  end;
.
.
.
// Realtime Counter abfragen und merken
  Rdtsc(EAX,EDX);
  UInt64(T_Count).Lo := EAX;
  UInt64(T_Count).Hi := EDX;
  // IA32_APERF_MSR abfragen und merken
  Rdmsr(IA32_APERF_MSR,EAX,EDX);
  UInt64(A_Count).Lo := EAX;
  UInt64(A_Count).Hi := EDX;
  // IA32_MPERF_MSR abfragen und merken
  Rdmsr(IA32_MPERF_MSR,EAX,EDX);
  UInt64(M_Count).Lo := EAX;
  UInt64(M_Count).Hi := EDX;
  //Warten ohne CPU-Last, die Genauigkeit steigt mit steigender Wartezeit
  Sleep(250);
  // Performance Counter und Delta berechnen
  QueryPerformanceCounter(P_Delta);
  P_Delta := P_Delta-P_Count;
  // Realtime Counter abfragen und Delta berechnen
  Rdtsc(EAX,EDX);
  UInt64(T_Delta).Lo := EAX;
  UInt64(T_Delta).Hi := EDX;
  T_Delta := T_Delta-T_Count;
  // IA32_APERF_MSR abfragen und Delta berechnen
  Rdmsr(IA32_APERF_MSR,EAX,EDX);
  UInt64(A_Delta).Lo := EAX;
  UInt64(A_Delta).Hi := EDX;
  A_Delta := A_Delta - A_Count;
  // IA32_MPERF_MSR abfragen und Delta berechnen
  Rdmsr(IA32_MPERF_MSR,EAX,EDX);
  UInt64(M_Delta).Lo := EAX;
  UInt64(M_Delta).Hi := EDX;
  M_Delta := M_Delta - M_Count;
.
.
.
Die Ausgabe sieht nun so aus:

T_Delta : 499578708 T_Count : 443978902840440
M_Delta : 7999140 M_Count : 75242284529760
A_Delta : 3998292 A_Count : 47422740994605
P_Delta : 894070 P_Count : 794571775763
Nomineller Prozessortakt : 2000
Aktueller Prozessortakt : 1000

T_Delta : 499655388 T_Count : 443980903020900
M_Delta : 7133940 M_Count : 75242391276468
A_Delta : 3565674 A_Count : 47422794368151
P_Delta : 894208 P_Count : 794575355381
Nomineller Prozessortakt : 2000
Aktueller Prozessortakt : 1000

T_Delta : 499559364 T_Count : 443982903294864
M_Delta : 22331856 M_Count : 75242513536524
A_Delta : 11165232 A_Count : 47422855498137
P_Delta : 894036 P_Count : 794578935166
Nomineller Prozessortakt : 2000
Aktueller Prozessortakt : 1000

Danke für die Hilfe.
  Mit Zitat antworten Zitat
devidespe

Registriert seit: 7. Sep 2006
Ort: Berlin
434 Beiträge
 
Delphi 10.4 Sydney
 
#8

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 10:11
Besteht vielleicht die Möglichkeit, das gesamte Projekt noch einmal mit dem korrigierten Code zu posten ?

Danke im Voraus...
Devid
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.168 Beiträge
 
Delphi 12 Athens
 
#9

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 10:23
schau mal in deine SysUtils ... in neueren Delphis dürfte UInt64Rec schon definiert sein.
wär allerdings auch praktisch gewsen, wenn die WinRing0-Dinger dieses schon als UInt64 exportieren würden

ja und wegen dem BS ... hab auch nicht mit sowas gerechnet, aber bis auf 'nen fast fertigen Download ist nichts verloren gegengen (nja, der Firefox hat leider Probleme mit dem DL-Fortsetzten) ... nja und ich war da noch der Meinung hier sei 'nen BilligIntel drin (nja, aber wenn ich so überlege ... dessen Vorgänger war ein Pentium 1, also so weit lag ich ja nich daneben )

Zitat von El.Blindo:
Ist halt für Core Prozessoren.
na ich hab doch
'ne gegnerische One-Core-CPU


@devidespe
wenn's dir egal ist wie das 32-Bitproblem (shl 16) und die UIntInt64 gelöst wurden, dann brauchst nur sein Projekt nehmen und das Eine durch meine .PAS ersetzten

oder du nimmst sein Projekt und erstzt einige Ausschnitte dieser .PAS mit den Codestücken aus seinem letztem Post.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
El.Blindo

Registriert seit: 24. Okt 2006
18 Beiträge
 
#10

Re: Taktfrequenz berechnen, Realtime Counter, Überlauf ?

  Alt 28. Jan 2008, 13:51
@devidespe

Bitte
Angehängte Dateien
Dateityp: pas main_323.pas (6,6 KB, 24x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


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 06:45 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