Noch kürzer Warten als Sleep(1)
-
Nee, die Frage isses nicht
Zwar ist die Optimierung von inline-assembly weit außerhalb des Standards, dem Compiler wäre es also nicht verboten.
Aber der einzige Zweck von NOP ist: nix machen. Wenn man ein NOP reinschreibt, hat man sich also was bei gedacht.
Übliche Anwendungsfälle sind: Warten auf externe Hardware, "Füllbyte" bei automatischer Codegenerierung / patchen. Wenn man für einen speziellen Prozessor optimiert, kann man mit einem geschickten NOP außerdem pipeline stalls und ungünstige pipeline-Zuordnung vermeiden - mit NOP kann es also sogar schneller sein.
-
Eigentlich suche ich eine Alternative zu Sleep() da ich gemerkt hab da Sleep sehr ungenau ist. Es wartet mal so mal so. Da muss es doch alternativen geben? Am besten welche die nicht viel CPU Auslastung brauchen.
-
Entweder du sagst Windows, dass du keine Rechenzeit abgeben willst und versuchst möglichst lang, dass dein Thread aktiv bleibt (100% Auslastung), oder du sagst eben Windows, dass es deinen Thread irgendwann wieder aktivieren soll (Sleep) - aber wie schon gesagt: Windows ist kein Echtzeit-Betriebssystem!
-
Die alternative "genauer und keien Rechenzeit" gibt es nicht (es sei denn, man schiebt Windows einen Echtzeit-Kernel unter)
Multimedia-Timer kommen noch am nächsten, aber schon mit merklicher Last für das System. Die Auflösung ist aber auch in ms.
Die Begrenzungen kommen nicht aus dem Sleep selbst, sondern dem Thread Scheduler. Sleep sagt dem Scheduler nur, das der thread für die nächsten N ms nicht geschedult werden soll.
Die generische Lösung bleibt Sleep. Wenn die Genauigkeit von Sleep ncith ausreicht, muß man halt erstmal fragen: warum.
-
peterchen schrieb:
Die alternative "genauer und keien Rechenzeit" gibt es nicht (es sei denn, man schiebt Windows einen Echtzeit-Kernel unter)
Multimedia-Timer kommen noch am nächsten, aber schon mit merklicher Last für das System. Die Auflösung ist aber auch in ms.
Die Begrenzungen kommen nicht aus dem Sleep selbst, sondern dem Thread Scheduler. Sleep sagt dem Scheduler nur, das der thread für die nächsten N ms nicht geschedult werden soll.
Die generische Lösung bleibt Sleep. Wenn die Genauigkeit von Sleep ncith ausreicht, muß man halt erstmal fragen: warum.
Warum? Ich programmiere ein Spiel mit Winapi und wenn ich keinen Sleep Befehl einbaue läuft ja alles megaschnell!
Ich hab gehört das man die 12ms Schritte von Sleep() auf 1 ms Schritte kürzen kann mit SetSystemTimeAdjustment() allerdings krieg ich da die Fehlermeldung dass der Client ein erforderliches recht nicht besitzt.
-
joomoo schrieb:
Ich programmiere ein Spiel mit Winapi und wenn ich keinen Sleep Befehl einbaue läuft ja alles megaschnell!
Vielleicht solltest du die Bewegungen in deinem Spiel von "Weg pro Frame" auf "Weg pro Zeit" umstellen. Dann bist du nämlich relativ unabhängig von der tatsächlichen Framerate.
-
joomoo schrieb:
Warum? Ich programmiere ein Spiel mit Winapi und wenn ich keinen Sleep Befehl einbaue läuft ja alles megaschnell!
Das macht man aber nicht mit sleep, denn jeder ausführungsblock kann unterschiedlich lange dauern und mit sleep() können keine Nachrichten verarbeitet werden.
Mach es so:
/* global */ bool ende = false; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { /* Spiel einrichten, bilder laden und so */ DWORD idle; /* die Spielschleife */ while (!ende) { idle = GetTickCount(); /* aktuellen Millisekundenstand hollen */ /* Nachrichten abhandeln */ while(PeekMessage(&messages, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&messages); DispatchMessage(&messages); } /* Spiel Code */ /* und nun die Frame Bremse */ while ((GetTickCount() - idle) < 40) /* 25 Frame Sekunde */ ; } }
So läuft es nun mit 25 Bilder Sekunde, wie beim Film
-
MiC++ha schrieb:
joomoo schrieb:
Warum? Ich programmiere ein Spiel mit Winapi und wenn ich keinen Sleep Befehl einbaue läuft ja alles megaschnell!
Das macht man aber nicht mit sleep, denn jeder ausführungsblock kann unterschiedlich lange dauern und mit sleep() können keine Nachrichten verarbeitet werden.
Mach es so:
/* global */ bool ende = false; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { /* Spiel einrichten, bilder laden und so */ DWORD idle; /* die Spielschleife */ while (!ende) { idle = GetTickCount(); /* aktuellen Millisekundenstand hollen */ /* Nachrichten abhandeln */ while(PeekMessage(&messages, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&messages); DispatchMessage(&messages); } /* Spiel Code */ /* und nun die Frame Bremse */ while ((GetTickCount() - idle) < 40) /* 25 Frame Sekunde */ ; } }
So läuft es nun mit 25 Bilder Sekunde, wie beim Film
Das hat ich auch schon gedacht, aber das geht nicht, da GetTickCount() genauso ungenau ist wie sleep! Ein Tick sind nur ungefähr 10 ms...
-
Eigentlich sollte man bei Games die Bewegungen unabhängig von den Frames, sondern abhängig von der Zeit machen.
Frame-Bremse sollte höchstens benutzt werden, wenn sonst bei schnellen Grakas einige Werte zu klein/zu groß werden um damit noch gescheit rechnen zu können...
...aber die Thematik gehört wohl eher ins Spiele/-Grafikprogrammierungs-Forum...
-
Ich brauche einfach nur einen Ersatz für Sleep() der mindestens ms genau ist...
-
Nein das brauchst du nicht. Hör auf uns.
-
MiC++ha hat doch schon eine Lösung mit Hilfe von QueryPerformanceCounter gepostet, oder funktionierte die nicht?!
-
flenders schrieb:
MiC++ha hat doch schon eine Lösung mit Hilfe von QueryPerformanceCounter gepostet, oder funktionierte die nicht?!
Doch das Funktioiert, nur unter 1000MHz kann mann keine hohe genauigkeit garantieren, aber wer hat weniger als 1000MHz außer meine Frau(500 Celeron)? :::Geitz ist geil:::
Ne mal genau gesagt, wir wissen nicht genau den Zusammenhang, den sagt er auch nichts da er sonst ins Spieleforum verschwindet, aber mit dieser "Wer wird Millionär" raterei, kommen wir auch nicht weiter.
Diese Spielschleife die ich anzeigte kann auch leicht mit QueryPerformanceCounter() verfeinert werden, die allgemeine Regel lautet ::Sleep() vermeiden, und das hat seine Gründe, aber wenn man QueryPerformanceCounter() benutzt auf (ab) einen 800MHz Rechner kann mann sich
schon in guter genauigkeit bewegen (je nach Prozess anzahl).
Solange wir keine genauen Infos haben, bringt das alles nichts, und ich denke wenn diese Infos kommen ist es Vermutlich doch was fürs Spieleforum.Genauer als Sleep
Auch dazu wurden gewisse Antworten gegeben, und bei spielen giebts keine Genauigkeit, sondern so ne Art Ablauf Perfomance, wenn dein Spiel bei dir gut und Genau läuft, muß es nicht gleich auch bei mir genauso gut laufen, und schon gar nicht mit "Schlafen".
-
MiC++ha schrieb:
flenders schrieb:
MiC++ha hat doch schon eine Lösung mit Hilfe von QueryPerformanceCounter gepostet, oder funktionierte die nicht?!
Doch das Funktioiert, nur unter 1000MHz kann mann keine hohe genauigkeit garantieren, aber wer hat weniger als 1000MHz außer meine Frau(500 Celeron)? :::Geitz ist geil:::
Ne mal genau gesagt, wir wissen nicht genau den Zusammenhang, den sagt er auch nichts da er sonst ins Spieleforum verschwindet, aber mit dieser "Wer wird Millionär" raterei, kommen wir auch nicht weiter.
Diese Spielschleife die ich anzeigte kann auch leicht mit QueryPerformanceCounter() verfeinert werden, die allgemeine Regel lautet ::Sleep() vermeiden, und das hat seine Gründe, aber wenn man QueryPerformanceCounter() benutzt auf (ab) einen 800MHz Rechner kann mann sich
schon in guter genauigkeit bewegen (je nach Prozess anzahl).
Solange wir keine genauen Infos haben, bringt das alles nichts, und ich denke wenn diese Infos kommen ist es Vermutlich doch was fürs Spieleforum.Genauer als Sleep
Auch dazu wurden gewisse Antworten gegeben, und bei spielen giebts keine Genauigkeit, sondern so ne Art Ablauf Perfomance, wenn dein Spiel bei dir gut und Genau läuft, muß es nicht gleich auch bei mir genauso gut laufen, und schon gar nicht mit "Schlafen".
Keine genauere Lösung als Sleep wurde gepostet. Außer das mit dem QueryPerformanceCounter, aber das klappt bei mir nicht, denn es wartet plötzlich kürzer wenn man eine Taste gedrückt hält. Keine Ahnung warum. Ich hab aber auch mehr als 1 Ghz (1,83ghz). Aber es muss doch eine Möglichkeit geben? Es gibt doch soviele Spiele die so funktionieren...
-
Es gibt doch soviele Spiele die so funktionieren...
welche?
Ich beschäftige mich auch mit Spieleprogrammierung, aber nur zum teil, aber mir ist nicht bekannt das man irgendwo das Spiel einfriert um die Frames runter zu setzten, es wird meines wissens immer mit Timing gearbeitet.
-
MiC++ha schrieb:
Es gibt doch soviele Spiele die so funktionieren...
welche?
Ich beschäftige mich auch mit Spieleprogrammierung, aber nur zum teil, aber mir ist nicht bekannt das man irgendwo das Spiel einfriert um die Frames runter zu setzten, es wird meines wissens immer mit Timing gearbeitet.
Was ist den Timing?
-
joomoo schrieb:
Was ist den Timing?
Zeitgesteuert!
Ich gebe an wie lange es dauert das sich ein Objekt von Punkt A nach Punk B bewegt, egal ob 20FPS oder 150FPS. Und wenn ich eine Framebremse will, dann mache ich das auf der Art wie schon erwähnt, aber ->Bild ausgeben->Prog schlafen lassen->nächstes Bild ist "FATAL_ERROR_STYLE_FOR_GAME_DEVS"
-
MiC++ha schrieb:
joomoo schrieb:
Was ist den Timing?
Zeitgesteuert!
Ich gebe an wie lange es dauert das sich ein Objekt von Punkt A nach Punk B bewegt, egal ob 20FPS oder 150FPS. Und wenn ich eine Framebremse will, dann mache ich das auf der Art wie schon erwähnt, aber ->Bild ausgeben->Prog schlafen lassen->nächstes Bild ist "FATAL_ERROR_STYLE_FOR_GAME_DEVS"
Und wie gebe ich das an? Wie kann ich Zeit messen??
-
Um das zu Vereinfachen gehen wir mal von einem 2D Game aus und als "Zeit" ms aus GetTickCount(), für 3D emphelt sich äher PerformanceCounter.
sagen wir du hast ein Objekt, egal wie es aus sieht dem giebts du eine geschwindigkeit vor, als Beispiel 200px/Sekunde
DWORD alteZeit, neueZeit; alteZeit = GetTickCount(); /* Spielschleife */ while (!Spielende) { /* hier event. Messages bearbeiten */ /* Hintergrund zeichnen etc. */ /* nun Rechnen wir die Geschwindigkeit in ms um */ float msSpeed = Objekt->Speed / 1000; /* Objekt->Speed ist int 200 */ neueZeit = GetTickCount(); int PixelBewegung = msSpeed * (neueZeit - alteZeit); Objekt->PositionX += PixelBewegung; /* für X Richtung, als Beispiel */ /* und nun das Objekt zeichnen */ /* etc. */ alteZeit = neueZeit; }
Wenn du nun 100FPS hast bewegt es sich um 2 Pixel, hast du 50FPS bewegt es sich um 4 Pixel, in jedem Fall bewegt es sich um 200 Pixel pro Sekunde.
Das war jetzt eine vereinfachte Darstellung zum besseren Verständnis.
-
MiC++ha schrieb:
Um das zu Vereinfachen gehen wir mal von einem 2D Game aus und als "Zeit" ms aus GetTickCount(), für 3D emphelt sich äher PerformanceCounter.
sagen wir du hast ein Objekt, egal wie es aus sieht dem giebts du eine geschwindigkeit vor, als Beispiel 200px/Sekunde
DWORD alteZeit, neueZeit; alteZeit = GetTickCount(); /* Spielschleife */ while (!Spielende) { /* hier event. Messages bearbeiten */ /* Hintergrund zeichnen etc. */ /* nun Rechnen wir die Geschwindigkeit in ms um */ float msSpeed = Objekt->Speed / 1000; /* Objekt->Speed ist int 200 */ neueZeit = GetTickCount(); int PixelBewegung = msSpeed * (neueZeit - alteZeit); Objekt->PositionX += PixelBewegung; /* für X Richtung, als Beispiel */ /* und nun das Objekt zeichnen */ /* etc. */ alteZeit = neueZeit; }
Wenn du nun 100FPS hast bewegt es sich um 2 Pixel, hast du 50FPS bewegt es sich um 4 Pixel, in jedem Fall bewegt es sich um 200 Pixel pro Sekunde.
Das war jetzt eine vereinfachte Darstellung zum besseren Verständnis.Genauso will ich das auch machen. Nur das gibt es dieses eine Problem: GetTickCount() ist verdammt ungenau das ein Tick ca. 12 ms sind. Das reicht mir nicht.