Autor Beitrag
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 13.10.08 09:17 
Hi,

der Befehl QueryPerformanceCounter basiert ja AFAIK intern auf dem RDTSC-Befhl. Wie ermittelt aber QueryPerformanceFrequency die zugehörige Zählfrquenz?

Hab auch schon ein wenig geschaut, aber bisher keine wirkliche Info zum Thema gefunden: Weder bei Sandpile, noch in diversen Linux-Kernel-Archiven.

Wäre über einige etwas genauere, technische Details sehr erfreut.

MfG,
BenBE.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 13.10.08 10:27 
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19321
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 13.10.08 11:00 
Das ist ihm sicherlich klar was da steht^^

Zum Thema:
Ich hatte jetzt nicht die Zeit mir das genauer anzuschauen, aber ich glaube in diesem Dokument findest du dazu Informationen, es handelt sich um die Dokumentation zur Systemprogrammierung von Intel, ab 18.10 ist einiges zu finden, so viel, dass ich es mir nicht genauer anschauen konnte jetzt:
download.intel.com/d...r/manuals/253669.pdf

(Liste unter: www.intel.com/products/processor/manuals/)
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mo 13.10.08 14:24 
Das sieht schon mal interessant aus ... Wobei ich die Intel-Doku jetzt auf Anhieb auch nicht Blicke ... Scheint aber so, als ob die bei Intel auch nicht direkt ein Vorgehen dafür haben ...

Soweit habsch nur gefunden, dass das vom jeweiligen Prozessor abhängig ist, ob das die Busfrequenz, oder die Maximale Boot-Frequenz ist.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 13.10.08 19:29 
Intel schreibt:
.
Enhanced Timer
This Enhanced Timer (Etimer) is based on two Windows* API functions; QueryPerformanceCounter and QueryPerformanceFrequency. There is no way to know which frequency Microsoft is using to implement those two functions on any given platform. But one thing for sure is that the frequency of that timer will never change during the course of timing. The timer can be either the chipset timer or the power management timer or something else. The Etimer is created to meet two goals: first, it can be used as a high precision timer which is accurate to nanoseconds and second it is independent of Speedstep, Enhanced Speedstep technology or similar technologies. The OS will check to see if the system has a high performance clock built-in. If it has and the system has no energy saving mechanism like Speedstep Technology in it, this timer will take advantage of this clock, which is most likely the processor clock. Otherwise, the timer will use another constant frequency clock like the chipset, BIOS or the power management timer. There are things to consider when using this timer in your applications. Since the Etimer uses the system calls QueryPerformanceCounter and QueryPerformanceFrequency, it will incur an overhead associated with system calls. The Etimer also has another overhead associated with the checking mechanism that ensures that all the measurements are taken on the same processor. If the overhead is too much for your applications, you can consider using the processor clock by calling the instruction RDTSC. Let us explore the situation when we can use RDTSC. In multi-processor systems, normally, Windows synchronizes the time stamp counters (TSC's) on all processors. The TSC values are not exactly the same, but they are only off by a few counts. Windows will synchronize the TSC's when the returned value of the function QueryPerformanceFrequency is the same as that of the processor clock. If that is the case, you can safely use the TSC's without worrying which processor they are from. This way you can eliminate all the overheads associated with the mechanism that forces all the measurements to be done on the same processor.
-------------------------------------------------------
GOOGLE Übersetzung
-------------------------------------------------------
Dieser Enhanced Timer (eTimer) basiert auf zwei Windows * API-Funktionen; QueryPerformanceCounter und QueryPerformanceFrequency. Es gibt keine Möglichkeit zu wissen, welche Frequenz Microsoft ist mit der Umsetzung dieser beiden Funktionen in einer bestimmten Plattform. Aber eine Sache ist für Sie sicher, dass die Häufigkeit, dass der Timer wird nie ändern im Laufe des Timing. Der Timer kann entweder der Chipsatz-Timer oder die Power-Management-Timer oder irgendwas anderes sind. Die eTimer erstellt wird, um zwei Ziele: Erstens, es kann verwendet werden, wie ein hoher Präzision, die Timer ist genau zu Nanosekunden und zweites ist es unabhängig von Speedstep, Enhanced SpeedStep-Technologie oder ähnliche Technologien. Das Betriebssystem wird prüfen, um zu sehen, ob das System hat eine hohe Leistung Uhr built-in. Wenn dies der Fall ist und das System hat keine Energieeinsparung Mechanismus wie Speedstep Technology in ihm, diesem Timer wird die Vorteile dieser Uhr, die am ehesten der Prozessor Clock. Andernfalls wird der Timer wird eine weitere Konstante Frequenz Uhr wie der Chipsatz, BIOS oder die Power-Management-Timer. Es gibt Dinge, die bei der Verwendung dieser Timer in Ihre Anwendungen. Da die eTimer nutzt das System fordert QueryPerformanceCounter und QueryPerformanceFrequency, es wird ein Overhead-Kosten im Zusammenhang mit System fordert. Die eTimer hat auch eine andere Gemeinkosten im Zusammenhang mit der Überprüfung Mechanismus, der sicherstellt, dass alle Messungen werden auf dem gleichen Prozessor. Wenn der Overhead ist zu viel für Ihre Anwendungen, können Sie prüfen, mit dem Prozessor Clock, indem Sie die Anweisung RDTSC. Lassen Sie uns die Situation, wenn wir können RDTSC. In Multi-Prozessor-Systemen, in der Regel, Windows synchronisiert die Zeitstempel Zähler (TSC's) auf alle Prozessoren. Die TSC-Werte sind nicht genau das gleiche, aber sie sind nur durch ein paar zählt. Windows wird synchronisieren Sie die TSC's, wenn die Rückgabe der Funktion QueryPerformanceFrequency ist die gleiche wie die des Prozessors Uhr. Wenn dies der Fall ist, können Sie sicher Nutzung der TSC's ohne Besorgnis erregend hoch, was sie sind Prozessor aus. Auf diese Art können Sie beseitigen alle Gemeinkosten im Zusammenhang mit dem Mechanismus, der alle Kräfte der Messungen zu tun auf dem gleichen Prozessor.
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 15.10.08 11:47 
@hathor: Das M$ nichts Halbes und nix Ganzes gebaut hat, war mir klar. Mir ging es aber weniger um QPC\QPF, sondern wirklich um die Geschichte mit RDTSC. Aber schon mal gut zu wissen, dass eine M$-Implementation nicht sehr gesprächig ist ;-)

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 15.10.08 20:32 
Nocheinmal INTEL:

Reading Performance-Monitoring and Time-Stamp Counters

The RDPMC (read performance-monitoring counter) and RDTSC (read time-stamp counter)
instructions allow an application program to read the processor’s performance-monitoring and
time-stamp counters, respectively.
The Pentium 4 and Intel Xeon processors have 18 40-bit performance-monitoring counters and
the P6 family processors have 2 40-bit counters. These counters can be used to record either the
occurrence of events or the duration of events. The events that can be monitored are model
specific and include the number of instructions decoded, number of interrupts received, of
number of cache loads. Each counter can be set up to monitor a different event, using the system
instruction WRMSR to set up values in the one of the 45 ESCR and one of the 18 CCCR MSRs
(for Pentium 4 and Intel Xeon processors) or in either the PerfEvtSel0 or the PerfEvtSel1 MSR
(for the P6 family processors). The RDPMC instruction loads the current count from a counter
into the EDX:EAX registers.
The time-stamp counter is a model-specific 64-bit counter that is reset to zero each time the
processor is reset. If not reset, the counter will increment ~6.3 x 1015
times per year when the processor is operating at a clock rate of 200 MHz. At this clock frequency, it would take over 2000 years for the counter to wrap around. The RDTSC instruction loads the current
count of the time-stamp counter into the EDX:EAX registers.
See Section 15.8., “Performance Monitoring Overview”, and Section 15.7., “Time-Stamp
Counter”, for more information about the performance monitoring and time-stamp counters.
The RDTSC instruction was introduced into the IA-32 architecture with the Pentium processor.
The RDPMC instruction was introduced into the IA-32 architecture with the Pentium Pro
processor and the Pentium processor with MMX technology. Earlier Pentium processors have
two performance-monitoring counters, but they can be read only with the RDMSR instruction,
and only at privilege level 0.

TIME-STAMP COUNTER
The IA-32 architecture (beginning with the Pentium processor) defines a time-stamp counter
mechanism that can be used to monitor and identify the relative time of occurrence of processor
events. The time-stamp counter architecture includes the time-stamp counter
(IA32_TIME_STAMP_COUNTER MSR [called the TSC MSR in the P6 family and Pentium
processors]), an instruction for reading the time-stamp counter (RDTSC), a feature bit (TCS
flag) that can be read with the CPUID instruction, and a time-stamp counter disable bit (TSD
flag) in control register CR4.
Following execution of the CPUID instruction, the TSC flag in register EDX (bit 4) indicates
(when set) that the time-stamp counter is present in a particular IA-32 processor implementa-
tion. (See “CPUID—CPU Identification” in Chapter 3 of the IA-32 Intel Architecture Software
Developer’ s Manual, Volume 2.)
The time-stamp counter (as implemented in the Pentium 4, Intel Xeon, P6 family, and Pentium
processors) is a 64-bit counter that is set to 0 following the hardware reset of the processor.
Following reset, the counter is incremented every processor clock cycle, even when the
processor is halted by the HLT instruction or the external STPCLK# pin.
The RDTSC instruction reads the time-stamp counter and is guaranteed to return a monotoni-
cally increasing unique value whenever executed, except for 64-bit counter wraparound. Intel
guarantees, architecturally, that the time-stamp counter frequency and configuration will be such
that it will not wraparound within 10 years after being reset to 0. The period for counter wrap is
several thousands of years in the Pentium 4, Intel Xeon, P6 family, and Pentium processors.
Normally, the RDTSC instruction can be executed by programs and procedures running at any
privilege level and in virtual-8086 mode. The TSD flag in control register CR4 (bit 2) allows
use of this instruction to be restricted to only programs and procedures running at privilege level
0. A secure operating system would set the TSD flag during system initialization to disable user
access to the time-stamp counter. An operating system that disables user access to the time-
stamp counter should emulate the instruction through a user-accessible programming interface.
The RDTSC instruction is not serializing or ordered with other instructions. Thus, it does not
necessarily wait until all previous instructions have been executed before reading the counter.
Similarly, subsequent instructions may begin execution before the RDTSC instruction operation
is performed.
The RDMSR and WRMSR instructions can read and write the time-stamp counter, respectively,
as an MSR (at MSR address 10H). In the Pentium 4, Intel Xeon, and P6 family processors, all
64-bits of the time-stamp counter can be read with the RDMSR instruction (just as with the
RDTSC instruction). However, when the WRMSR instruction is used to write to the time-stamp
counter, only the low order 32-bits of the time-stamp counter can be written to, and the high-
order 32 bits cleared to all 0s.
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 16.10.08 07:18 
Wenn ich also

user profile iconhathor hat folgendes geschrieben Zum zitierten Posting springen:
Nocheinmal INTEL:

Reading Performance-Monitoring and Time-Stamp Counters

[...]
The time-stamp counter is a model-specific 64-bit counter that is reset to zero each time the
processor is reset. If not reset, the counter will increment ~6.3 x 1015
times per year when the processor is operating at a clock rate of 200 MHz. At this clock frequency, it would take over 2000 years for the counter to wrap around. [...]


und

user profile iconhathor hat folgendes geschrieben Zum zitierten Posting springen:
TIME-STAMP COUNTER

[...]
The time-stamp counter (as implemented in the Pentium 4, Intel Xeon, P6 family, and Pentium
processors) is a 64-bit counter that is set to 0 following the hardware reset of the processor.
Following reset, the counter is incremented every processor clock cycle, even when the
processor is halted by the HLT instruction or the external STPCLK# pin.
[...]


richtig interpretiere, heißt das, dass RDTSC mit der (aktuellen) CPU-Geschwindigkiet (Wenn ich das processor clock cycle richtig deute), abhängig vom Techniken wie Cool&Quite, SpeedStepping, ..., läuft.

Blieb nur noch die Frage, wie man die CPU-Frequenz möglichst ohne großen Aufwand (also wenn möglich ohne Messung) ermittelt (Hab da vollen Hardware-Zugriff).

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 16.10.08 08:20 
Ich erspare mir MSR-Pfriemeleien - ist ja bei AMD sicher anders, als bei INTEL und nehme die WINDOWS-Funktionen:
(zusätzliche Funktionen können entfernt werden)
.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Label3: TLabel;
    MaxMhz1: TLabel;
    Timer1: TTimer;
    Label2: TLabel;
    CurrentMhz1: TLabel;
    Memo1: TMemo;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

const
  powrproflib = 'powrprof.dll';

type
  PROCESSOR_POWER_INFORMATION = packed record
    Number: Cardinal;
    MaxMhz: Cardinal;
    CurrentMhz: Cardinal;
    MhzLimit: Cardinal;
    MaxIdleState: Cardinal;
    CurrentIdleState: Cardinal;
  end;
  PPROCESSOR_POWER_INFORMATION = ^PROCESSOR_POWER_INFORMATION;

  TCPUFrequency = packed record
    CurrentMhz: Cardinal;
    MaxMhz: Cardinal;
    MhzLimit: Cardinal;
  end;

var
  CPUFrequency: TCPUFrequency;

type
  TFrameTimer = class
  private
    fBaseTime: Extended;
    function GetTime: Extended;
  public
    constructor Create;
    procedure Reset;
    property BaseTime: Extended read fBaseTime write fBaseTime;
    property Time: Extended read GetTime;
  end;

implementation

{$R *.dfm}

constructor TFrameTimer.Create;
begin
  Reset;
end;

procedure TFrameTimer.Reset;
var
  QPFreq, QPCount: Int64;
begin
  QueryPerformanceFrequency(QPFreq);
  QueryPerformanceCounter(QPCount);
  fBaseTime := (QPCount / QPFreq);
end;

function TFrameTimer.GetTime: Extended;
var
  QPFreq, QPCount: Int64;
begin
  QueryPerformanceFrequency(QPFreq);
  QueryPerformanceCounter(QPCount);
  Result := (QPCount / QPFreq) - fBaseTime;
end;

{ end TFrameTimer }
//-----------------------------------------------------------------------------
function CallNtPowerInformation(InformationLevel: DWORD; InPutBuffer: Pointer; InputBufferSize: ULONG; OutPutBuffer:
  Pointer; OutPutBufferSize: ULONG): DWORD; stdcallexternal powrproflib;

function GetCPUFrequency(var CPUFrequency: TCPUFrequency): DWORD;
var
  ppi: PROCESSOR_POWER_INFORMATION;
  err: DWORD;
begin
  ZeroMemory(@ppi, sizeof(PROCESSOR_POWER_INFORMATION));
  err := CallNTPowerInformation(11nil0, @ppi, sizeof(PROCESSOR_POWER_INFORMATION));
  if err = 0 then
  begin
    CPUFrequency.CurrentMhz := ppi.CurrentMhz;
    CPUFrequency.MaxMhz := ppi.MaxMhz;
    CPUFrequency.MhzLimit := ppi.MhzLimit;
  end;
  result := err;
end;

function ReadFREQ : Boolean;
var
  err: DWORD;
begin
  ZeroMemory(@CPUFrequency, sizeof(TCPUFrequency));
  err := GetCPUFrequency(CPUFrequency);
  if err = 0 then result:= true else result:= false;
end;
//-----------------------------------------------------------------------------

procedure TForm1.Timer1Timer(Sender: TObject);
begin
If ReadFREQ = true then
BEGIN
MaxMhz1.Caption:= IntToStr(Round(CPUFrequency.MaxMhz div 100 +1)* 100)+' MHz';
CurrentMhz1.caption:= IntToStr(Round(CPUFrequency.CurrentMhz div 100 +1)* 100)+' MHz';
END;
end;

end.
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 16.10.08 08:39 
Sorry, aber ich arbeite Kernel-Mode unter Linux (RTAI), daher bringt mir die PowerProfile-Verwaltung von Windows recht wenig.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Do 16.10.08 09:29 
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 26.10.08 11:14 
Such mal nach:

IA32_MPERF
IA32_APERF

..use IA32_MPERF and IA32_APERF MSRs to get the measured performance
* over a period of time, while CPU is in C0 state.
* IA32_MPERF counts at the rate of max advertised frequency
* IA32_APERF counts at the rate of actual CPU frequency
* Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
* no meaning should be associated with absolute values of these MSRs.

Added:
Intel CPUs after Core Duo support two Model-Specific registers called IA32_MPERF and IA32_APERF.
MPERF counts at the maximum frequency the CPU supports, while APERF counts at the actual frequency.

The actual frequency is given by:

freq = max_frequency * APERF / MPERF

(if you have edit permissions, feel free to nicefy the equation above)

#define MSR_IA32_MPERF 0xE7
#define MSR_IA32_APERF 0xE8

You can read them with this flow

; read MPERF
mov ecx, 0xe7
rdmsr
mov mperf_var_lo, eax
mov mperf_var_hi, edx

; read APERF
mov ecx, 0xe8
rdmsr
mov aperf_var_lo, eax
mov aperf_var_hi, edx

but note that rdmsr is a privileged instruction and can run only in ring 0.


Zuletzt bearbeitet von hathor am So 26.10.08 12:22, insgesamt 1-mal bearbeitet
BenBE Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: So 26.10.08 11:35 
Das klingt alles schon recht gut. Ich schau bei Gelegenheit, ob die entsprechenden Funktionen (Lesen der MSRs, ...) über die Linux-Kernel-Header verfügbar sind. Im Fall von RDTSC war das nämlich der Fall.

Ansonsten schon mal Danke für die zahlreichen Links und Hinweise.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 26.10.08 14:37 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Hi,

der Befehl QueryPerformanceCounter basiert ja AFAIK intern auf dem RDTSC-Befhl. Wie ermittelt aber QueryPerformanceFrequency die zugehörige Zählfrquenz?...


.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
function RDTSC: Int64;
asm
  rdtsc
end;

function QueryPerformanceFrequency : Int64;
var
   startCycles, endCycles : Int64;
   aTime, refTime : TDateTime;
begin
   aTime:=Now;
   while aTime=Now do ;
   startCycles:=RDTSC;
   refTime:=Now;
   while refTime=Now do ;
   endCycles:=RDTSC;
   aTime:=Now;
   Result:=Round((endCycles-startCycles)/((aTime-refTime)*(3600*24)));
end;