Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi cpu zeit einer schleife auslesen (https://www.delphipraxis.net/115057-cpu-zeit-einer-schleife-auslesen.html)

ferby 5. Jun 2008 01:13


cpu zeit einer schleife auslesen
 
Hallo,

wie kann man in Delphi herausfinden wieviel CPU Zeit eine bestimmte Schleife verbraucht?

also zb


procedure TForm1.Btn1Click(Sender: TObject);
begin
while z_temp.next<>NIl do
z_temp:=z_temp.next;

showmessage('Schleife hat ' + ?? + ' CPU Zeiteinheiten verbraucht');
end;


wer eine ahnung?


(Möchte nicht Zählen wie viel Zeit vergangen ist, zwischen vor und nach der Schleife, sondern wirklich die verbrauchte
CPU Zeit anzeigen lassen)

Ferby

turboPASCAL 5. Jun 2008 01:16

Re: cpu zeit einer schleife auslesen
 
Zitat:

Zitat von Luckie
Die Forensuche sollte helfen: Hier im Forum suchenQueryPerformanceCounter.


SirThornberry 5. Jun 2008 07:52

Re: cpu zeit einer schleife auslesen
 
mit QueryPerformanceCounter misst man auch nur die Zeit zwischen 2 Punkten. Dabei wird aber eben auch nicht berücksichtigt wenn andere Prozesse und Threads zwischenzeitlich Rechenzeit abbekommen. Somit bekommt man, je nach dem wie viel andere Prozesse laufen, verschiedene Ergebnisse.

ferby 5. Jun 2008 11:01

Re: cpu zeit einer schleife auslesen
 
Hallo,

es muss doch eine Möglichkeit geben, unabhängig von anderen Prozessen zu messen...

Bernhard Geyer 5. Jun 2008 11:21

Re: cpu zeit einer schleife auslesen
 
Ich mach sowas immer mit AQTime

OregonGhost 5. Jun 2008 11:23

Re: cpu zeit einer schleife auslesen
 
Unabhängig von anderen Prozessen geht nicht ohne weiteres. Wenn du aber hinreichend viele Tests machst (insbesondere bei sehr kurzen Funktioen wichtig), bekommst du trotzdem vergleichbare Ergebnisse. Profiler wie AQTime unterstützen dich dabei, dann musst du dich nicht um den Kleinkram kümmern.

Luckie 5. Jun 2008 11:35

Re: cpu zeit einer schleife auslesen
 
Zitat:

Zitat von OregonGhost
Unabhängig von anderen Prozessen geht nicht ohne weiteres.

Natürlichh geht das. Mit MSDN-Library durchsuchenGetThreadTimes kan nman die CPU-Zeit ermitteln die der Code im User mode bzw. im Kernel mode verbringt.

OregonGhost 5. Jun 2008 15:18

Re: cpu zeit einer schleife auslesen
 
Nun, wie hier zu lesen ist (und auch an diversen anderen Orten), ist auch GetThreadTimes aus verschiedenen Gründen nicht völlig unabhängig von anderen Threads. Auch hier wäre also eine hinreichende Zahl von Tests notwendig, und wenn die zu testende Funktion z.B. eine Wait-Funktion aufruft, stimmen die Zeiten erst recht nicht mehr und die Wartezeit ist auch noch besonders intensiv von anderen laufenden Prozessen und Threads beeinflusst.

ferby 5. Jun 2008 18:43

Re: cpu zeit einer schleife auslesen
 
Hello,

wir müssen doch nur die Zeitdiverenz messen....

Gibt es in Delphi eine Funktion, die mir die Anzahl der Sekunden seit 1.1.1970 zurückliefert?
So wie die Time Funktione in C?

Cyf 5. Jun 2008 20:00

Re: cpu zeit einer schleife auslesen
 
Zitat:

Zitat von ferby
Hello,

wir müssen doch nur die Zeitdiverenz messen....

Gibt es in Delphi eine Funktion, die mir die Anzahl der Sekunden seit 1.1.1970 zurückliefert?
So wie die Time Funktione in C?

:?: Ich dachte das Ganze soll unabhängig ablaufen?
Die Zeitdifferenz wird davon beeinflusst, was "im Hintergrund" so noch abläuft, aber wenn doch ungenauere Werte reichen sollte, kannst du das hiermit (am besten mehrfach) austesten:

Delphi-Quellcode:
procedure TForm1.UngenauMessen;
var
  Zeit: Cardinal;
begin
  Zeit := GetTickCount;

  //Befehlesfolge deren Zeitdauer bestimmt werden soll
  sleep(2000);
  //

  Button1.Caption:= (IntToStr(GetTickCount - Zeit) + ' ms');
end;
oder genauer, aber rechenintensiver:

Delphi-Quellcode:
procedure TForm1.GenauMessen; //genauer aber mehr Ressourcenverbauch
var
  a, b, c: Int64;
begin
  QueryPerformanceFrequency(a);
  QueryPerformanceCounter(b);

  //Befehlesfolge deren Zeitdauer bestimmt werden soll
  sleep(2000);
  //

  QueryPerformanceCounter(c);

  Button1.Caption:= Format('%.3f ms',[(c - b) * 1000 / a]);  //Ausgabe in ms
end;
Hoffe das ist hilfreich.

Horst_ 5. Jun 2008 20:41

Re: cpu zeit einer schleife auslesen
 
Hallo,

etwas genauer, zählt Takte
Man kann auch CPUF bestimmen, aber bei Cool&quite und Konsorten etwas schwieriger..

Bei´m PentiumM
Startaufruf ~54 Takte
StoppAufruf ~56 Takte (Obwohl viel mehr gerechnet wird)
Delphi-Quellcode:
{APPTYPE Console}
uses
  sysutils;

const
  CPUF = 1700000;//CPU frequenz in khz

type
  tZeit = record
            t0, //letzter Start
            t1, //letzter Stopp
            dt, // Differenz Stopp-Start
            tsum, //Summe aller Differenzen
            StartStoppCnt : int64; //Anzahl Aufrufe
          end;
var
  tges,tdummy : tZeit;
  i : integer;
  j : int64;

procedure ZeitInit(var t:tZeit);
begin
  with t do
    begin
    t0:=0;
    t1:=0;
    dt:=0;
    tsum:=0;
    StartStoppCnt := 0;
    end;
end;

procedure ZeitStart(var t:tZeit);ASSEMBler;

asm
  // EAX ist der Zeiger auf t und muss gerettet werden
  // Weil der Compiler sonst durcheinander kommt
  MOV ECX,EAX
  rdtsc
  Xchg EAX,ECX
  mov Dword Ptr [t.t0], ecx
  mov Dword Ptr [t.t0+4], edx
end;

procedure ZeitStopp(var t:tZeit);Assembler;
asm
  // EAX ist der Zeiger auf t und muss gerettet werden
  // Weil der Compiler sonst durcheinander kommt
  MOV ECX,EAX
  rdtsc;
  Xchg EAX,ECX
  //Zeit in tStopp speichern
  mov Dword Ptr [t.t1], ecx
  mov Dword Ptr [t.t1+4], edx
  //dt bestimmen
  SUB ecx,Dword Ptr [t.t0]
  SBB edx,Dword Ptr [t.t0+4]
  mov Dword Ptr [t.dt], ecx
  mov Dword Ptr [t.dt+4], edx
  //tsum berechnen
  ADD ecx,Dword Ptr [t.tsum]
  ADC edx,Dword Ptr [t.tsum+4]
  MOV Dword Ptr [t.tsum],EcX
  MOV Dword Ptr [t.tsum+4],EDX
  //Cnt erhöhen Achtung nur 32 bit genutzt
  INC Dword Ptr [t.StartStoppCnt]
end;

begin
  ZeitInit(tGes);
  ZeitStart(tges);
   for i := 1 to 1000000 do
    j := sqr(i);
  ZeitStopp(tges);
  WriteLn(Format(' Gesamttakte %12d ',[tges.tsum]));
  WriteLn(Format(' Gesamtzeit  %12.6f ms',[tges.tsum/CPUf]));
  WriteLn(Format(' Gesamtzahl  %12d ',[tges.StartStoppCnt]));
  Writeln;

  //Wird länger dauern wegen des Overhead's
  //Bei mir 56 Takte pro Durchlauf
  ZeitInit(tGes);
  ZeitInit(tDummy);
  ZeitStart(tges);
  for i := 1 to 1000000 do
     begin
     ZeitStart(tDummy);
     end;
  ZeitStopp(tges);

  WriteLn(Format(' Gesamttakte %12d ',[tges.tsum]));
  WriteLn(Format(' Gesamtzeit  %12.6f ms',[tges.tsum/CPUf]));
  WriteLn(Format(' Gesamtzahl  %12d ',[tdummy.StartStoppCnt]));
  Writeln;

  //Bei mir 58 Takte pro Durchlauf
  ZeitInit(tGes);
  ZeitInit(tDummy);
  ZeitStart(tges);
  for i := 1 to 1000000 do
     begin
     ZeitStopp(tdummy);
     end;
  ZeitStopp(tges);
  WriteLn(Format(' Gesamttakte %12d ',[tges.tsum]));
  WriteLn(Format(' Gesamtzeit  %12.6f ms',[tges.tsum/CPUf]));
  WriteLn(Format(' Gesamtzahl  %12d ',[tdummy.StartStoppCnt]));
  Writeln;
end.
Gruß Horst

ferby 5. Jun 2008 20:48

Re: cpu zeit einer schleife auslesen
 
Hello,

thx,

werds so irgendwie machen ;-)

himitsu 5. Jun 2008 22:42

Re: cpu zeit einer schleife auslesen
 
zu Horst_s Vorschlag:
beim Messen mit dem TimeStampCounter muß man aber inzwischen höllisch aufpassen!

z.B.:
http://www.delphipraxis.net/internal...ighlight=rdtsc
und weitere Beiträge

Und ich glaube mal gehört zu haben, daß der auf einigen Prozessoren unabhängig vom CPU-Takt läuft,
was erstmal nicht sooo schlimm ist, aber ich laß z.B. meinen Prozessor dynamisch takten (heißt der Takt ändert sich je nach CPU-Auslastung) und da würde dann der gemessene Wert nicht unbedingt mit der CPU-Zeit übereinstimmen.

Horst_ 6. Jun 2008 06:04

Re: cpu zeit einer schleife auslesen
 
Hallo,

ich dachte es würden eben genau die Cpu-Takte gezählt.
Ob bei 800 Mhz oder 2200 Mhz. Die absolute Zeitdauer ist natürlich flexibel.
Bei Mehrfachkernen ist natürlich die Möglichkeit das WinAPI-aufrufe auf einem anderen Kern in anderer Frequenz laufen schon groß.
Aber ich gehe davon aus, das man nur seinen eigenen Algo testet, und dort nur einen sehr kurzen Abschnitt, sonst eben gettickcount.
Das bringt mich auf eine Idee:
Zusätzlich könnte man ja dtMin und dtMax bestimmen und eintragen. Dann weiß man, was man von den Daten zu halten hat.

Gruß Horst
P.S.: Mich haben eigentlich nur die Taktzahlen interessiert,.
Eine Taktmessung ist doch wenigstens für eine CPU machbar, auch bei unterschiedlicher Taktrate, die hat man doch nicht im Griff.

himitsu 6. Jun 2008 06:38

Re: cpu zeit einer schleife auslesen
 
RDTSC mißt im Prinzip nur dieProzessortakte, aber eben alle Takte wärend der Messung, incl. der Takte für die anderen, wärend der Messdauer laufenden Programme.

und da bei dynamisch getakteten CPUs diese Taktzyklen nicht genau einer bestimmten Zeiteinheit entsprechen, haben wohl einige CPU-Hersteller sich gedacht, sie erzeugen diesen über Zeitsynchron über einen externen/separaten Taktgenerator.


jedenfalls kommt es mir so vor, als wenn ich Dieses mal in Bezug auf die Messung der CPU-Geschwindigkeit gelesen zu hatte.
(wo man ja einfach über eine gewisse Zeit die "CPU"-Takte mißt)

Cyf 6. Jun 2008 13:11

Re: cpu zeit einer schleife auslesen
 
Zitat:

Zitat von Horst_
Delphi-Quellcode:
// EAX ist der Zeiger auf t und muss gerettet werden
  // Weil der Compiler sonst durcheinander kommt

Nur um Verwirrung vorzubeugen, der Zeiger muss hier nur gerettet werden, da später übe die Zugriffe auf t auf ihn (also EAX) zugegriffen wird, generell stehen EAX. EBX und EDX zur freien Verfügung.

RDTSC bringt, wie schon genannt, isbesondere auf Multicoresystemen und bei Energiesparfunktionen (Taktveränderung), oder auch bei "out-of-order execution" gewisse Probleme mit sich (siehe auch -> englische Wikipedia "RDTSC").
Wenn man diese Probleme nicht ausschließen kann, sind QueryPerformanceFrequency() + QueryPerformanceCounter(), denke ich, die bessere Alternative.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz