Moin zusammen,
ich zerbreche mir gerade den Kopf darüber, wie ich am besten das Pipes-and-Filter Pattern in C++ unter Linux realisiere.
Was möchte ich machen:
Ich habe eine handvoll Module, die auf der einen Seite Daten (mehrere Datenströme) hinein bekommen, diese umrechnen und auf der anderen Seite Datenströme an das nächste Modul weiterreichen. Die Datenströme innerhalb des Modules müssen zwingend auf den Sample genau (Messignal - kein Audio; Anforderungen ähnlich) verarbeitet werden.
Das letzte Modul soll dann eine nette QT-Applikation sein, die mir das Ergebnis in Echtzeit präsentiert.
Ich schreibe hier so lässig Modul: Es sind in Wirklichkeit Shared-Objects, die während das Programm läuft eingeladen und ausgeführt werden können. - Je nach belieben des Nutzers. Somit kann z.B. im Live-Betrieb eine neuere Modul-Version angestartet werden.
Das Problem, vor dem ich gerade stehe ist folgendes:
Soll ich die geladenen Module jeweils als Threads oder als Prozess starten? Da ich oben bereits etwas von "Echtzeit" geschrieben habe, sollen die Daten so schnell es geht verarbeitet werden. Keine harten Echtzeitanforderungen, die besagen, daß innerhalb von ein paar Millisekunden das Ergebnis auf dem Schirm zu sein hat...
Nachteil bei Prozessen ist, daß ich noch eine komplette Kommunikationsinfrastruktur implementieren müsste, sodaß Signale ausgewertet oder gesendet werden können und Logging-Informationen an ein Logging-Interface versendet werden.
Bei Threads habe ich ein stdin und -out. Die Daten können über die lokalen Variablen weitergereicht werden, sodaß es hier auch keine Probleme gibt.
Welcher C++-Guru mag mich in diesem Sinne erleuchten?
Grüße,
Lev
Pipes-And-Filter-Pattern...
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: Pipes-And-Filter-Pattern...
Ich glaube viel wirst du hier auch nicht drehen können, außer dass du den Kernel höflich bittest, den Prozess mit niedrigem Nice-Wert den Vorzug zu geben.Da ich oben bereits etwas von "Echtzeit" geschrieben habe, sollen die Daten so schnell es geht verarbeitet werden.Keine harten Echtzeitanforderungen, die besagen, daß innerhalb von ein paar Millisekunden das Ergebnis auf dem Schirm zu sein hat...
Wie du im Titel erwähnt hast, könntest du die Standardeingabe und die Standardausgabe zur Ein/Ausgabe deines Datenstroms nutzen. Das machen einige Programme auch. Wenn du das mit einem fork(2) machst, könntest du hier auch alle Variablen übergeben. Die Priorität könntest du mit setpriority(2) setzen.Nachteil bei Prozessen ist, daß ich noch eine komplette Kommunikationsinfrastruktur implementieren müsste, sodaß Signale ausgewertet oder gesendet werden können und Logging-Informationen an ein Logging-Interface versendet werden.
Wieso müsstest du eine komplette Kommunikationsinfrastruktur implementieren?
stdout hättest du bei einzelnen Prozessen auch, denn die Kindprozesse werden auf die gleiche Datei (oder Standardausgabe) schreiben, wie der Elternprozess.Bei Threads habe ich ein stdin und -out.
Ich glaube, hier wären eher Threads zu empfehlen, da du die Daten bereits lokal in deinem Prozessspeicher bereitgestellt hast. Auch müsste der Overhead zum starten/stoppen etwas geringer sein.Das Problem, vor dem ich gerade stehe ist folgendes:
Soll ich die geladenen Module jeweils als Threads oder als Prozess starten?
Der Nachteil wäre, dass du gegen Abstürze innerhalb der Module nichts machen kannst. Die Priorität könntest du mit pthread_setschedparam(3) setzen.
Kurz: ich sehe keinen Vorteil darin Prozesse zu bevorzugen.
Haters gonna hate, potatoes gonna potate.
Re: Pipes-And-Filter-Pattern...
Hi fat-lobyte!
Wenn jedoch nur Threads erzeugt werden, dann wird es einen Kommunikationsoverhead geben, wenn ein Thread auf eine andere CPU ausgelagert werden muss...
Grüße,
Lev
Und ich erhoffe mir Zeitvorteile in einer Mehr-CPU-Umgebung, weil jeder Prozess seinen eigenen Speicherbereich hat in dem er arbeiten kann. Übergeben werden die Daten über Fifos. Jede CPU erhält genau die Daten, die sie für ihre Prozesse braucht.Ich glaube, hier wären eher Threads zu empfehlen, da du die Daten bereits lokal in deinem Prozessspeicher bereitgestellt hast. Auch müsste der Overhead zum starten/stoppen etwas geringer sein.
Wenn jedoch nur Threads erzeugt werden, dann wird es einen Kommunikationsoverhead geben, wenn ein Thread auf eine andere CPU ausgelagert werden muss...
Die Fifos müssen eingerichtet werden, die Prozess-Signalauswertung - Signale an andere Prozesse senden-, Konfigurationsmöglichkeiten der einzelnen Module - und das Logging nicht vergessen, damit die Meldungen nicht im Chaos versinken...Wieso müsstest du eine komplette Kommunikationsinfrastruktur implementieren?
Grüße,
Lev
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Re: Pipes-And-Filter-Pattern...
Wieso sollte das schneller sein? Alle Prozesse müssen über den selben Speicher-Bus auf den vergleichsweise langsamen Hauptspeicher zugreifen(im Vergleich zum Cache). Zudem musst du die Daten in einem Prozess erst hübsch verpacken, Serialisieren, nach außen Bringen und im anderen Prozess wieder entsprechend entgegen nehmen.Und ich erhoffe mir Zeitvorteile in einer Mehr-CPU-Umgebung, weil jeder Prozess seinen eigenen Speicherbereich hat in dem er arbeiten kann.
Hier musst du sogar noch mehr sicherstellen, dass der andere Prozess die Daten auch entsprechend schnell entgegen nimmt, denn nur weil er auf einem anderen Kern läuft, heißt es ja nicht, dass er nicht von irgendwas blockiert wird. Zudem kann der User einen Prozess abschießen, und du würdest evt nicht mal merken, dass dem so ist.
Threads bieten hier gewisse vorteile. Sie laufen auch auf mehreren Kernen, sie können aber auch Daten innerhalb des Programms durchreichen. Du kannst direkt Pointer auf entsprechende Datenstrukturen übergeben und weitermachen, ohne die Daten irgendwie neu zu verpacken. So zumindest meine Meinung.
MfG cloidnerux.
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: Pipes-And-Filter-Pattern...
Jede CPU enthält auch mit Threads genau die Daten, die sie braucht - jede CPU hat ihren eigenen Cache, ihre eigenen Register und spielt in ihrem "eigenen" Speicherbereicht (es kann auch der Teilbereich eines einzigen Prozesses sein). Mit Prozessen hast du im Gegenteil MEHR Wahrscheinlichkeit, dass sich der Kernel dazu entscheidet die CPU-Zeit einem anderen Prozess zu geben.Leverator hat geschrieben:Und ich erhoffe mir Zeitvorteile in einer Mehr-CPU-Umgebung, weil jeder Prozess seinen eigenen Speicherbereich hat in dem er arbeiten kann. Übergeben werden die Daten über Fifos. Jede CPU erhält genau die Daten, die sie für ihre Prozesse braucht.
Wie bereits von cloidnerux erwähnt, wirst du mit Prozessen auf jeden fall mehr Overhead haben, als mit Threads.Leverator hat geschrieben:Wenn jedoch nur Threads erzeugt werden, dann wird es einen Kommunikationsoverhead geben, wenn ein Thread auf eine andere CPU ausgelagert werden muss...
Ja, da hast du schon recht, das ist ein Mehraufwand. Deswegen sind Threads auch IMHO geeigneter.Die Fifos müssen eingerichtet werden, die Prozess-Signalauswertung - Signale an andere Prozesse senden-, Konfigurationsmöglichkeiten der einzelnen ModuleWieso müsstest du eine komplette Kommunikationsinfrastruktur implementieren?
Wenn du irgendwas tolles machst, dann brauchst du in beiden Fällen Logging.und das Logging nicht vergessen, damit die Meldungen nicht im Chaos versinken...
Haters gonna hate, potatoes gonna potate.
Re: Pipes-And-Filter-Pattern...
Wenn du Qt verwenden möchtest, kannst du die Threads gleich darüber laufen lassen. In Verbindung mit dem "Signal and Slot" Mechanismus von Qt sollte dein Programm "schnell genug" sein bzw. reagieren können.as letzte Modul soll dann eine nette QT-Applikation sein, die mir das Ergebnis in Echtzeit präsentiert.
Gleiches auch für deine Fifos - läßt sich wunderbar mit Qt realisieren.
Gruß
There is no place like 127.0.0.1