Autor Beitrag
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 28.10.07 21:29 
Ich habe mal SLEEP-Vergleichsmessungen gemacht und war über das Ergebnis doch etwas erstaunt.
Das Resultat ist: Das in DELPHI vorhandene SLEEP() ist unter 30 msec SLEEP(30) unbrauchbar!

Zum Vergleichen habe ich die GetTickCount-Function genutzt - die Genauigkeit ist besser als 2 msec, im Durchschnitt ist die Ungenauigkeit 1 msec, d.h. ab 30 msec sind die Abweichungen unbedeutend.
(Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days.)

Ergebnisse der 10 msec und 20 msec Werte sind offensichtlich rein zufällig und können sogar 30 msec-Werte weit übertreffen! Extremer Fehler, wenn CPU-Load 100% ist.

Neue Version: 20071030
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von hathor am Di 30.10.07 10:40, insgesamt 1-mal bearbeitet
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: So 28.10.07 21:35 
Haste ein Sleep auf GetSystemTimeToFileTime-Basis und QPC\QPF-Basis getestet?

_________________
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 28.10.07 21:41 
user profile iconBenBE hat folgendes geschrieben:
Haste ein Sleep auf GetSystemTimeToFileTime-Basis und QPC\QPF-Basis getestet?


Nee. Hast Du einen "brauchbaren" Code?

Meinst Du sowas?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure UpdateTimeStamp(H: THandle);
var
  FT: TFileTime;
begin
  GetSystemTimeAsFileTime(FT);
  SetFileTime(H, nilnil, @FT);
end;
//oder sowas:
Begin
    sQpcMinResMls := FormatOutput(Format('%3.9n',[aTimer.getTimeMeasureAs(tsMilliSec,1,tkQPC)]));
    sQpcMinResMic := FormatOutput(Format('%3.9n',[aTimer.getTimeMeasureAs(tsMicroSec,1,tkQPC)]));
    sQpcMinResNan := FormatOutput(Format('%3.9n',[aTimer.getTimeMeasureAs(tsNanosSec,1,tkQPC)]));
    sQpcApiOvdNat := FormatOutput(IntToStr(aTimer.FQpcOverhead)+' units ');
    aReal := aTimer.GetOptimalMeasure(aTimer.FQpcOverhead, tkQPC, aTimeScale);
    sQpcApiOvdOpt := Format('%s (%3.9n)',
                     [TimeScale2Str[Ord(aTimeScale)], aReal ]);
  End;
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: So 28.10.07 22:17 
Mh...? Sleep ist bei mir genausogut wie PseudoASM und Kernel bei 20ms und gleich wie alle anderen bei 30ms und 10ms. Delay und SysDelay weichen bei 20ms um 15ms von Sleep / PseudoASM / Kernel ab. Bei 100% CPU-Auslastung nicht viel anders.
Einloggen, um Attachments anzusehen!
_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 28.10.07 23:19 
Oh Mann, der Tickcountfehler bei 100% Last ist aber hoch mit 15msec!
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: So 28.10.07 23:42 
Mit GetSystemTimeAsFileTime erhälst Du nen Zeitstempel ähnlich dem von QPC zurück, den man zur Zeitmessung nutzen kann. Näheres dazu steht im MSDN.

_________________
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.
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 29.10.07 00:28 
Hab das Programm mal eben etwas erweitert:

Problem: Du misst falsch!

Hab mal eben noch RDTSCDelay, RDTSCSleep und SystemTimeWait implementiert (oben genannte Messverfahren) und dabei selbst für RDTSC Abweichungen von 15 msec angezeigt bekommen (obwohl RDTSC nachweislich auf meiner CPU mit >500MHz* taktet) ...

Ferner würd ich dich bitten, dein Programm mal bitte etwas aufzuräumen.

Ein weiteres Problem: Zeitkritische Anweisungen werden NICHT korrekt zeitkritisch behandelt. So erzeugst Du durch falsche Handhabung bei der PseudoASM-Variante ein nicht-deterministisches Verhalten, da die Messung außerhalb des ASM-Blocks stattfindet.

*RDTSC auf AMD-CPUs läuft mit CPU-Takt (2GHz bei mir); bei Intels meistens mit 3,6MHz.
Einloggen, um Attachments anzusehen!
_________________
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 29.10.07 00:37 
RDTSC geht absolut nicht!

@BenBE
Deine Änderungen verschlechtern die Werte.
Einloggen, um Attachments anzusehen!
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 29.10.07 00:47 
Nicht RDTSC geht nicht, sondern die Art, wie Du die Zeiten misst, ist kacke...

Du kannst nicht erwarten, dass wenn Du mit'm Lichtmikroskop ein Atom betrachtest, dass Du dann Quantenfluktuationen bis zur Heisenbergschen Unschärfe nachverfolgen kannst. Genau das machst Du aber, wenn Du mit GetTickCount versuchst, die Qualität von RDTSC zu messen.

Nutze bitte zur Zeitauswertung eine genauere Methode als GetTickCount, dann solltest Du qualitativ bessere Ergebnisse erhalten.

_________________
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 29.10.07 00:52 
user profile iconBenBE hat folgendes geschrieben:
Nicht RDTSC geht nicht, sondern die Art, wie Du die Zeiten misst, ist kacke...


Ich werde nicht meine CPU auf eine Frequenz festnageln, um RDTSC verwenden zu können - es ist für Zeitmessungen nicht geeignet. BASTA!
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Mo 29.10.07 08:12 
user profile iconhathor hat folgendes geschrieben:
Oh Mann, der Tickcountfehler bei 100% Last ist aber hoch mit 15msec!

So wie du den Fehler von GetTickCount bestimmst, kann man den auch nicht bestimmen.

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
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 29.10.07 10:45 
Stellen wir also fest: Die genutzten Mess-Verfahren sind ungeeignet.

Ich bau's die Tage mal auf QPC\QPF-Messung um.

_________________
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.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 29.10.07 10:59 
user profile iconhathor hat folgendes geschrieben:
Ich habe mal SLEEP-Vergleichsmessungen gemacht und war über das Ergebnis doch etwas erstaunt.
Das Resultat ist: Das in DELPHI vorhandene SLEEP() ist unter 30 msec SLEEP(30) unbrauchbar!

Als aller erstes, sollte man sich fragen, was Sleep überhaupt macht:
Zitat:
This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds.

Der Rest der dem Thread zur Verfügung gestellten Zeitscheibe wird also an das System abgegeben und der Thread die angegeben Zeitspanne für nicht zuteilungsfähig erklärt. Da unter Windows NT eine Zeitscheibe ca. 20 Millisekunden lang ist, ist es unmöglich einen Thread für weniger als 20 Millisekunden "schlafen zu legen".
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 29.10.07 17:50 
Titel: Gettickcount ist offensichtlich VIEL ungenauer...
Gettickcount ist offensichtlich VIEL ungenauer, als es rechnerisch sein dürfte!
Deshalb habe ich die Zeitmessung geändert:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.Button47Click(Sender: TObject);
var   a, b, c: Int64; r: real;
begin
  QueryPerformanceFrequency(a);
  QueryPerformanceCounter(b);
  Sleep(1000); //<<<< Die Zeitdauer dieses Befehls wird gemessen
  QueryPerformanceCounter(c);
  r:= (c - b) * 1000 / a;
  Label47.Caption := FloatToStrF(r, ffFixed, 123)+' msec';
end;
Einloggen, um Attachments anzusehen!
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 29.10.07 18:10 
user profile iconLuckie hat folgendes geschrieben:

Der Rest der dem Thread zur Verfügung gestellten Zeitscheibe wird also an das System abgegeben und der Thread die angegeben Zeitspanne für nicht zuteilungsfähig erklärt. Da unter Windows NT eine Zeitscheibe ca. 20 Millisekunden lang ist, ist es unmöglich einen Thread für weniger als 20 Millisekunden "schlafen zu legen".


@Luckie

Bei Dir ist ein Update überfällig!
Du hast Dein Wissen offensichtlich aus der WINDOWS95-Ära.
Nichts für ungut: Man sollte immer jede WINDOWS-Version auf den Prüfstand stellen!
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 29.10.07 20:27 
hathor: Hast Du für QPF\QPC_S oder QPF\QPC_D die Messung in dem Screenie drin?

Können ja noch nen Kontest draus machen, wer's mit einfachen Mitteln so genau wie möglich hinbekommt, eine vorgegebene Zeit zu stoppen ...

BTW: SystemTime kann auch im <MSec-Bereich ähnlich wie QPC genutzt werden. Aber wie es die Messungen zeigen: Windows interpoliert dies nicht vollständig. Über einen Registry-Switch (Default 15625uSec) kann man die Update-Zeit einstellen.

Bitte zeige auch für jegliche Varianten die CPU-Auslastung mit an, wenn dies möglich ist ... (Hoffe, du hast da in Bezug auf QPC\QPF_D was festgestellt *G*

Mal sehen, ob hier jemand einen Zusammenhang mit den ersten Screenshots dieses Programms erkennt *G*

_________________
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 29.10.07 21:17 
Ich habe Folgendes mitgetestet:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure SystemTimeWait(milliseconds: cardinal);
var
    S1: _FILETIME;
    S1V: Int64 absolute S1; //Equal Memory for S1 and S1V; simply an alias definition
    S2: _FILETIME;
    S2V: Int64 absolute S2; //Equal Memory for S2 and S2V; simply an alias definition
Begin
    GetSystemTimeAsFileTime(S1);
    S2V := S1V + milliseconds * 10 * 1000//Convert msec to hnsec

    While S1V < S2V do
        GetSystemTimeAsFileTime(S1);
end;

procedure DelayQPC(t: cardinal);//entspricht Deinem 'procedure RDTSCDelay(milliseconds: cardinal);'
var  a, b: Int64;
Begin
    QueryPerformanceFrequency(b);
    QueryPerformanceCounter(a);
    b := a + (b * t) div 10000;
    While a < b do QueryPerformanceCounter(a);
end;

Die Version mit dem eingebetteten SLEEP habe ich nicht mitgetestet, denn die kann ja nicht besser sein, als der Test Nr.1.
Für die Messungen musste ich den Timer für die CPU-Usage und CPU-Freq. abschalten !!!
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Mo 29.10.07 22:04 
Könntest du mal die neue Version oben anhängen?

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 29.10.07 22:22 
user profile iconhathor hat folgendes geschrieben:
user profile iconLuckie hat folgendes geschrieben:

Der Rest der dem Thread zur Verfügung gestellten Zeitscheibe wird also an das System abgegeben und der Thread die angegeben Zeitspanne für nicht zuteilungsfähig erklärt. Da unter Windows NT eine Zeitscheibe ca. 20 Millisekunden lang ist, ist es unmöglich einen Thread für weniger als 20 Millisekunden "schlafen zu legen".


@Luckie

Bei Dir ist ein Update überfällig!
Du hast Dein Wissen offensichtlich aus der WINDOWS95-Ära.
Nichts für ungut: Man sollte immer jede WINDOWS-Version auf den Prüfstand stellen!

In wie fern?
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: Di 30.10.07 09:47 
Die Version mit dem integriertem Sleep ist in Bezug auf die CPU-Belastung vorteilhafter. Ferner wäre jedoch interessant, wie die Routine be Last-Situationen reagiert. 50ms sind zwar erstmal jenseits von Gut und Böse in Bezug auf die Sleep-Toleranz, bei ungünstiger Zeitscheiben-VErteilung (hohe Auslastung) könnte es aber durchaus zu merklichen ungenauigkeitn kommen.

_________________
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.