Funktion die Programm für Milisekunden schalfen legt

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
tobb
Beiträge: 1032
Registriert: 27.01.2006 17:48:13

Funktion die Programm für Milisekunden schalfen legt

Beitrag von tobb » 24.07.2007 15:57:11

Hi,

ich versuche mir gerade eine portable Funktion zu schreiben die ein bestimmte Anzahln von Milliskeunden wartet.

Code: Alles auswählen

	#ifdef WIN32
		#include "windows.h"
	#else
		#include "unistd.h"
	#endif
    //Wait the specific milli seconds (and check which system is used)
    inline void CrossSleep(unsigned int MilliSeconds)
    {
        #ifdef WIN32
            Sleep(MilliSeconds);
        #else
            usleep(MilliSeconds * 1000);
        #endif
    }
Unter Windows schläft ein CrossSleep(1) ca 2ms... was noch aktzeptabel ist...
Unter Linux (Ubuntu 7.04 Feisty) verschläft ein CrossSleep(1) allerdings ganze 13ms... was absolut inakzeptabel ist...
Gibts noch genauere Funktionen für Linux?

cosmac
Beiträge: 4576
Registriert: 28.03.2005 22:24:30

Beitrag von cosmac » 24.07.2007 23:05:26

hi,

theoretisch wäre nanosleep das Richtige für dich.
Evt. gibt's das auch unter Windows (es ist POSIX).

Praktisch hängt die mögliche Auflösung vom verwendeten Kernel ab, üblich
sind 10, 4 und 1 ms, bei Etch sind 4 ms Standard. Mit selbstgebauten Kernen
sind auch noch höhere Auflösungen möglich. Das entscheidende Kernel-Macro
ist CONFIG_HZ. Wenn die gewünschte Wartezeit kleiner als dieser Wert sein
soll, geht's eigentlich nicht. Bis zu 2 ms haben die 2.4er Kernel in einer Schleife
gewartet, die 2.6er machen das wohl nicht mehr.

Dann gibt es inzwischen die neuen "tickless" Kernel, wo nanosleep endlich
richtig funktionieren könnte - aber das ist noch zu neu für mich. Also, so richtig
portabel wird wohl etwas aufwändiger...
Beware of programmers who carry screwdrivers.

tobb
Beiträge: 1032
Registriert: 27.01.2006 17:48:13

Beitrag von tobb » 24.07.2007 23:14:45

Im Grunde genommen suche ich sowas
Allegro Dolumentation hat geschrieben: void rest(unsigned int time);

[...]

Passing 0 as parameter will not wait, but just yield. This can be useful in order to "play nice" with other processes. Other values will cause CPU time to be dropped on most platforms. This will look better to users, and also does things like saving battery power and making fans less noisy.
Wenn man 0 übergibt, entlastet man den Prozessor.

Beispiel

Code: Alles auswählen

while(true)
{
}
Dieser Code lastet die CPU zu 100% aus...

Code: Alles auswählen

while(true)
{
    rest(0);
}
Dieser COde lies die CPU Auslastung auf fast 30% sinken...

Sowas suche ich eigentlich!

cosmac
Beiträge: 4576
Registriert: 28.03.2005 22:24:30

Beitrag von cosmac » 25.07.2007 03:59:48

bist du sicher, daß du sowas brauchst? Ich dachte, das
gab's nur beim MacOS und vielleicht auf Atari und Amiga?
Oder willst du etwa sowas wie Allegro selber bauen?

"Bremsen" von CPU-lastigen Programmen

So wie ich das verstehe, hat unter Linux ein usleep(3*1000)
die gleiche Wirkung wie ein rest(0) -- das Programm gibt die
Kontrolle bis zum Ende der laufenden Zeitscheibe ab. Das ist
aber normal nicht nötig, weil der Kernel die CPU-Zeit gerecht
verteilt. Wenn man dabei ein Programm benachteiligen will,
nimmt man normalerweise den Befehl "nice".

Warten auf externe Ereignisse

Auf Echtzeit-Ereignisse im ms-Bereich zu reagieren, ist so nicht
möglich. Dafür kann das Programm aber meist select() benutzen.
Damit läuft es beim Eintritt des Ereignisses (z.B. Tastendruck)
sofort weiter oder, im Fehlerfall, nach Ablauf eines Time-Out.
So ergeben sich Reaktionszeiten deutlich unter 1 ms. Das hat
aber mit rest() nichts zu tun.

Strom sparen

Daß "while (true)" mehr Strom braucht als nichts tun, ist ja mal
klar, aber sollte "nichts tun" nicht weit unter 30% brauchen?
Egal - grundsätzlich ist jede Art von Polling boese(tm)
Beware of programmers who carry screwdrivers.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 25.07.2007 12:26:26

mir ist nicht ganz klar, was du jetzt wirklich suchst.
tobb hat geschrieben:
Allegro Dolumentation hat geschrieben: void rest(unsigned int time);

Passing 0 as parameter will not wait, but just yield.
Ein "usleep(0)" entspricht dem "rest(0)". Daher es wird nicht gewartet, der Prozeß wird "unterbrochen" und in die Warteschlange eingereiht (yield).
tobb hat geschrieben:Unter Windows schläft ein CrossSleep(1) ca 2ms... was noch aktzeptabel ist...
Unter Linux (Ubuntu 7.04 Feisty) verschläft ein CrossSleep(1) allerdings ganze 13ms... was absolut inakzeptabel ist...
Gibts noch genauere Funktionen für Linux?
wenn du beide Systeme (Windows oder Linux) unter eine hohe Last stellst, wirst du auf beiden Systemen über 100ms kommen können
wenn beide Systeme idlen, solltest du sowohl unter Windows, als auch unter Linux auf einen Wert von ca 1-2ms kommen könne, ansonsten ist etwas faul.

Die Funktionen sind ja genau. Wenn die Zeit abgelaufen ist UND dein Prozeß die höchste Priorität (aus Sicht des Schedulers) erreicht hat, wird der Scheduler auch deinem Prozeß die CPU zuteilen.
Nachdem Prozesse unterbrechbar sind, kann es dir auch passieren, daß direkt vor dem "usleep" ein Kontextswitch stattfindet, wodurch der "usleep" Aufruf gleich als erster Systemcall abgesetzt wird, nach dem deinem Prozeß die CPU wieder zugeteilt wurde. Daher würde dir auch keine "noch so genauer Funktion" eine größere Genauigkeit garantieren können!.

Gruß
gms

Benutzeravatar
npi
Beiträge: 567
Registriert: 03.08.2003 17:52:10

Beitrag von npi » 25.07.2007 13:07:57

hi,
wenn du so kurze Zeitintervalle auflösen musst, dann solltest du dich vielleicht mal mit nem Realtime-Kernel auseinandersetzen ([1] und [2]).

gruß,
npi

[1] http://de.wikipedia.org/wiki/RTLinux
[2]http://de.wikipedia.org/wiki/RTAI
"Bis zur Unendlichkeit, und noch viel weiter!"
--Buzz, Toystory

tobb
Beiträge: 1032
Registriert: 27.01.2006 17:48:13

Beitrag von tobb » 25.07.2007 14:10:10

Folgendes:
Ich bin dabei ein Spiel zu programmieren, dass nicht sondelrich aufwendig ist. Da ist es geradezu lächerlich wenn es 99% CPU in anspruchnimmt...
Ich habe jetzt herausgefunden, dass wenn ich mit select() 1 Millisekunde schlafe, die Framerate kaum runtergeht, das Spiel aber nur noch 3% CPU in anspruch nimmt....
Ich bin einfach gerne sparsam.... ;-)

Benutzeravatar
npi
Beiträge: 567
Registriert: 03.08.2003 17:52:10

Beitrag von npi » 25.07.2007 14:15:48

tobb hat geschrieben:Folgendes:
Ich bin dabei ein Spiel zu programmieren, dass nicht sondelrich aufwendig ist.
ok,
da brauchst du definitiv keinen Realtime-Kernel 8).
Aber bei nem Spiel brauchst du ja auch keine zeitliche Auflösung von einer Millisekunde.
Je nach Spielart würde ich das einfach in einer Endlosschleife ablaufen lassen, oder eben nur, wenn Ereignisse (zB von der Maus oder Tastatur) eintreten.

gruß,
npi
"Bis zur Unendlichkeit, und noch viel weiter!"
--Buzz, Toystory

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 25.07.2007 14:36:49

npi hat geschrieben: Je nach Spielart würde ich das einfach in einer Endlosschleife ablaufen lassen, oder eben nur, wenn Ereignisse (zB von der Maus oder Tastatur) eintreten.
das ist ja genau das "Einsatzgebiet" für die "select" Funktion

tobb
Beiträge: 1032
Registriert: 27.01.2006 17:48:13

Beitrag von tobb » 25.07.2007 14:45:01

Genau.

Ich brauch keine Funktion, die auf die Miliskeunde genau misst, aber mehr als 10ms sollten es dann schon nicht sein, weil sowas die Framerate von z.B. 600FPS auf 80 FPS bremsen kann...

Benutzeravatar
Joghurt
Beiträge: 5244
Registriert: 30.01.2003 15:27:31
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Joghurt » 25.07.2007 20:05:45

tobb hat geschrieben:weil sowas die Framerate von z.B. 600FPS auf 80 FPS bremsen kann...
Und das wäre jetzt schlimm, weil...?

Einen Unterschied zwischen 80 und 600 FPS nimmt doch keiner wahr

tobb
Beiträge: 1032
Registriert: 27.01.2006 17:48:13

Beitrag von tobb » 25.07.2007 20:18:57

Ein alter gebrechlicher PC bringt vllt mit aller Mühe 60 FPS auf die Reihe und das Sleep würde ihm dann vollends den Gar ausmachen und das ganze auf 6 FPS drosseln oder so...

Antworten