Forum: PC-Programmierung Strategie für Event-Scheduler


von Haro (Gast)


Lesenswert?

Hallo,

ich suche eine Strategie oder einen Algorithmus der mir hilft folgendes 
umzusetzen:

Ich habe eine Liste an Events. Diese sollen jeweils mit einer bestimmten 
Zykluszeit "ausgeführt" werden. Jedes Event ist dabei gleich 
priorisiert.
Außerdem kann nur dann ein Event ausgelöst werden wenn gerade kein 
weiteres aktiv ist. D.h. das vorherige Event sollte fertig abgearbeitet 
worden sein bevor ein neues gestartet wird. Unter Umständen verzögert 
sich also ein Event leicht.
Dazu folgendes Beispiel:
1
ev_1  5ms
2
ev_2  30ms
3
ev_3  100ms

Hier sind die Zykluszeiten großzügig gewählt. Es sollte also wenig 
Probleme geben. ev_2 und ev_3 werden natürlich nicht genau zum Zeitpunkt 
t=30ms oder t=100ms ausgeführt weil das schnelle ev_1 dort auch jeweils 
aktiv ist. Wie gesagt, dieses leichte Delay ist in Ordnung. Gehen wir 
davon aus, die Eventliste wird jede Millisekunde geprüft, so findet ev_2 
bei t=31ms und ev_3 bei t=101ms statt. Passt.

Ok, nun folgendes (problematisches) Beispiel:
1
ev_1  5ms
2
ev_2  10ms
3
ev_3  10ms
4
ev_4  5ms
5
ev_5  5ms
6
ev_6  5ms

Hier wird schon durch die bloße Anzahl der Events erreicht, das die 
Zykluszeit nicht mehr eingehalten werden kann. Zwar unschön, aber nun 
gut.
Allerdings: die Verzögerungen werden sich aufaddieren, und irgendwann 
wird dann ein Event "verschluckt", d.h. geht verloren.
Das ist zwar noch weniger schön, aber immer noch akzeptabel.
Was aber nicht sein darf ist, dass ein Event was relativ spät in der 
Liste auftaucht (z.B. ev_6) gar nicht mehr ausgeführt wird.
Ich muss sicherstellen, dass jedes Event selbst bei hoher "Eventlast" 
irgendwann drankommt.

Gibt es da eine günstige Strategie/Algorithmus?
Mein Ansatz wäre: ich merke mir die Position in der Liste des zuletzt 
ausgeführten Events.
Ich teste meine Liste jede Millisekunde auf anstehende Events. Dabei 
arbeite ich die Liste nicht von [0] bis [n-1] durch sondern starte 
jeweils bei der gemerkten Position. So wird früher oder später das Ende 
der Liste erreicht.

Leider fehlen mir die mathematischen Grundlagen um diesen Ansatz 
bewerten/mit anderen vergleichen zu können.

Wär meine Lösung praktikabel oder gibt es da bessere Ansätze?
Ein Betriebssystem-Scheduler hat wohl ähnliche Probleme zu lösen (wenn 
auch ungleich komplexer). Von daher denke ich dass es da schon Ansätze 
gibt.

Viele Grüße

von Purzel H. (hacky)


Lesenswert?

Man nimmt dazu eine timerschlange, also eine doppelt verkettete Liste, 
da ist erster parameter des gelinkten elementes die dauer vom voeriger 
her gespeichert. Nach abgearbeiteten Timer event wird der HW-timer auf 
die zu wartende Zeit gestellt. Der Timer arbeitet dann das jeweils 
anstehende Element ab. Einfuegen bedeutet nun sich von vorne hach hinten 
hangeln, und dann in die liste einfuegen.

etwa so ?

von Εrnst B. (ernst)


Lesenswert?

Statt einer Liste wär evtl. eine "priority queue" besser geeignet.
Die lässt sich einfach in ein Array mappen, also keine dynamische 
Speicherverwaltung nötig.
Abarbeiten/"pop" und Hinzufügen/"push" eines Jobs geht in O(log n), bzw. 
bei Array-Implementierung mit konstanter Länge: in O(1) ;)

Und schon ist sichergestellt, dass immer der dringenste Job an 
Array-Position 0 steht.


https://de.wikipedia.org/wiki/Vorrangwarteschlange

: Bearbeitet durch User
von Bitflüsterer (Gast)


Lesenswert?

Meiner Ansicht nach, gehst Du bei der Analyse nicht gründlich genug vor.

Du musst drei Aspekte berücksichtigen:
1. Die Zykluszeit in der die Ereignisse tatsächlich auftreten.
2. Die reine Verarbeitungszeit der Ereignisse.
3. Die jeweilige maximal zulässige Reaktionszeit auf die Ereignisse.

Kennzeichne in Deinen Skizzen den Zeitablauf. Es wird nicht klar ob die 
in der ersten Skizze gezeigte Zeit die selbe ist, wie in der zweiten. 
(Ich kann mir zwar was dabei denken, aber es geht ja um ein tieferes 
Verständnis bei Dir).

Ein weiterer Aspekt ist die Frage der Unterscheidung zwischen Abläufen 
und Bedingungen, die aus irgendwelchen ausserhalb Deiner 
Einflussmöglichkeit liegenden Gründen so sind wie sie sind, oder weil 
sie so sein sollen, oder weil es wünschenswert ist, das sie so sind. Je 
nachdem ergeben sich weitere Überlegungen, die recht vielfältig sind. 
Nicht umsonst gibt es ganze Bücher über das Thema.

von Haro (Gast)


Lesenswert?

Bitflüsterer schrieb:
> Nicht umsonst gibt es ganze Bücher über das Thema.

Das ist mir bewusst.
Nicht umsonst treffe ich Annahmen, die das Problem vereinfachen:
- wenn die Zykluszeit nicht eingehalten kann stört dies nicht
- es sollen im laufenden Betrieb keine neuen Events eingereiht werden
- hauptsache, ein Event wird irgendwann erreicht
- die Bearbeitungszeit eines Events ist vernachlässigbar

Das hier ist ein Nebenkriegsschauplatz. Kein RTOS Scheduler dessen 
Verhalten streng deterministiech sein muss. Ich bitte das zu beachten.

Gibts dazu Ideen, die besser geeignet sind als meine Ursprüngliche?

von Oliver S. (oliverso)


Lesenswert?

Du musst dir schlicht merken, wann ein Event in "absoluter" Zeit dran 
ist. Dann prüfst du von mir aus jede ms, ob denn jetzt einer dran ist. 
Wenn ja, arbeitest du den ab, und merkst dir, wenn der wieder dran ist. 
Danach solltest du noch prüfen, ob noch mehr Events "jetzt" dran sind, 
und die auch abarbeiten. Wenn alle aktuellen durch sind, geht es von 
vorne los.

Oliver

von uwe (Gast)


Lesenswert?


von Bitflüsterer (Gast)


Lesenswert?

Haro schrieb:
> Bitflüsterer schrieb:
>> Nicht umsonst gibt es ganze Bücher über das Thema.
>
> Das ist mir bewusst.
> Nicht umsonst treffe ich Annahmen, die das Problem vereinfachen:

Aus meiner Sicht machen sie es nicht einfacher. Man könnte sie klarer 
und strenger formulieren. Aber gut. Wenn es Dir reicht, soll es mir 
recht sein.

> Das hier ist ein Nebenkriegsschauplatz. Kein RTOS Scheduler dessen
> Verhalten streng deterministiech sein muss. Ich bitte das zu beachten.

Davon habe ich nichts geschrieben. Aus meiner Sicht schien es mir 
angebracht, erst einmal Grundlagen klarzustellen. Aber gut. Wenn Dir 
alles klar ist, soll es mir recht sein.

> Gibts dazu Ideen, die besser geeignet sind als meine Ursprüngliche?

Sicherlich. Ich hätte angenommen, das Du, um sie zu entwickeln und zu 
verstehen, ein paar Grundlagen anschauen solltest. Aber gut. Dir ist 
schon alles klar. Fehlt nur noch die Idee. :-)

von Bitflüsterer (Gast)


Lesenswert?

Wie ich darauf gekommen bin, dass Du Grundlagen benötigst?

> Leider fehlen mir die mathematischen Grundlagen um diesen Ansatz
> bewerten/mit anderen vergleichen zu können.

von Haro (Gast)


Lesenswert?

Ok, schaun wir uns die Punkte an.

Bitflüsterer schrieb:
> Du musst drei Aspekte berücksichtigen:
> 1. Die Zykluszeit in der die Ereignisse tatsächlich auftreten.
> 2. Die reine Verarbeitungszeit der Ereignisse.
> 3. Die jeweilige maximal zulässige Reaktionszeit auf die Ereignisse.

1. Ich zeichne auf einer Zeitachse Punkte für die auftretenden Events. 
Dabei sehe ich, dass unter Umständen mehrere Eventtimer gleichzeitig 
abgelaufen sind. Abhängig von den einzelnen Zykluszeiten und der Anzahl 
Events. Erhöhe ich die Zykluszeiten so entspannt sich die Situation, bis 
irgendwann wieder alles i.O. ist. Habe ich mehr Events, verschärft sich 
die Situation.

2. Da ein Event nun keinen kurzen Impuls mehr darstellt sondern Zeit 
braucht verschärft sich die Situation. Das Bild aus 1. ändert sich nicht 
großartig, allerdings ist es jetzt schwerer, wieder in den grünen 
Bereich zu kommen.

3. Es gibt keinen "Timeout". Solange jedes Event irgendwann kommt passt 
alles. Ich vermute, wenn ich meinen Ansatz aus dem Eröffnungspost 
umsetze habe ich irgendwann folgendes Verhalten:
Mit jedem Zyklus verschlechtert sich die Situation. Die Delays summieren 
sich auf. Irgendwann sind alle Eventtimer gleichzeitig abgelaufen. Dann 
wird die Liste einfach der Reihe nach abgearbeitet, Zykluszeiten spielen 
keine Rolle mehr. Das System bleibt in diesem Zustand.

Sind meine Betrachtungen soweit richtig?
Ich sehe da wenig Optimierungspotential, aber ich könnte wohl mit der 
Lösung leben, außer es gibt noch Vorschläge ;-)

von Oliver S. (oliverso)


Lesenswert?

Haro schrieb:
> Irgendwann sind alle Eventtimer gleichzeitig abgelaufen. Dann
> wird die Liste einfach der Reihe nach abgearbeitet, Zykluszeiten spielen
> keine Rolle mehr.

Wenn das in Ordnun für dich ist, schlage ich vor, du versetzt das System 
gleich in den Zeitpunkt "Irgendwann", und arbeitest einfach alle Events, 
die dann gar keine mehr sind, hintereinander ab, ganz ohne 
Eventscheduler.

Oliver

von Haro (Gast)


Lesenswert?

Jo mei, natürlich wär eine gewisse Ordnung schöner. Momentan hab ich die 
halt nur bei günstigen Parametern, abhängig von Eventzahl und deren 
Zykluszeiten.

Da ich aber auf keine optimalere Lösung komme (siehe mein 
Gedankenexperiment im letzten Beitrag) und hier auch nix kommt werd ich 
das wohl so beibehalten. Nebenkriegsschauplatz eben.

von Oliver S. (oliverso)


Lesenswert?

Haro schrieb:
> Da ich aber auf keine optimalere Lösung komme (siehe mein
> Gedankenexperiment im letzten Beitrag) und hier auch nix kommt

Na ja, zum ganz große Töne spucken fehlt dir dann doch etwas die 
Substanz. Aber egal, wenn es sowieso egal ist, wann und warum da irgend 
etwas ausgeführt wird, mach einfach. Ist dein Programm.

Oliver

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.