LabVIEWForum.de - Datenaustausch über Cluster in zwei While-Schleifen

LabVIEWForum.de

Normale Version: Datenaustausch über Cluster in zwei While-Schleifen
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Guten Abend zusammen,

ich versuche mir gerade eine Grundstruktur für ein Messprogramm aufzubauen. Dabei möchte ich in einer While-Schleife Werte die von Extern kommen verarbeiten und in Abhängigkeit des eingehenden Werts Flags setzen oder bestimmte Werte in einem Array speichern. All diese Daten habe ich in einem Cluster zusammengefasst und stelle dieses über einen Melder in einer zweiten While-Schleife zur Verfügung. In dieser Schleife läuft dann der eigentliche Zustandsautomat, der auf die Daten im Cluster zugreift und diese auch ändern kann.

Ein kleines Beispielprogramm habe ich angehängt und meine Frage wäre, ob das so eine sinnvolle Struktur ist oder ob es hierfür andere bzw. bessere Lösungsansätze gibt. Gerade das Aufschlüsseln des Clusters, Durchschleifen der gleichgebliebenen Werte und Ändern des entsprechenden Flags kommt mir doch sehr umständlich vor.

Insofern wäre ich für die ein oder andere Idee sehr dankbar!Smile
Hallo,

wenn du nur ein Element eines Clusters ändern willst, dann solltest du mit "Bundle by Name" arbeiten:
[attachment=62177]

Gruß, Jens
Hallo creo,

Zitat:meine Frage wäre, ob das so eine sinnvolle Struktur ist oder ob es hierfür andere bzw. bessere Lösungsansätze gibt.
Wenn du den Notifier "nur" als Datenspeicher missbrauchst, dann kannst du auch ein Shiftregister mit einem Indicator verwenden.
Oder einfach eine lokale/globale Variable nehmen.
Oder eine FGV (Functional Global Variable), um die Zugriffe auf die einzelnen Datenelemente zu kapseln.

Zitat:All diese Daten habe ich in einem Cluster zusammengefasst und stelle dieses über einen Melder in einer zweiten While-Schleife zur Verfügung. In dieser Schleife läuft dann der eigentliche Zustandsautomat, der auf die Daten im Cluster zugreift und diese auch ändern kann.
Wieso willst du überhaupt die Daten in einer Schleife erst mal sammeln, um den Cluster zur zweiten Schleife zu schicken? Warum nicht die Daten gleich in der zweiten Schleife sammeln und bearbeiten?
Wieso soll die zweite Schleife ebenfalls die Clusterelemente bearbeiten können? Dies führt sehr schnell zu Race-Conditions!

Ich würde einen zentralen Datenbuffer bevorzugen…
"Bundle by Name" macht das ganze auf jeden Fall schonmal deutlich übersichtlicher, danke!

Meine Daten werden vermutlich über einen CAN-Bus ankommen. Da hier auch viele Nachrichten enthalten sind, die mich nicht interessieren, wollte ich in der ersten Schleife nur die Kommunikation laufen lassen und hier die Daten mitschreiben, die für mich bestimmt sind. In der zweiten Schleife werden dann nur noch die Flags im Cluster abgefragt und entsprechend reagiert und hierüber auch auf die einzelnen Messdaten im Array zugegriffen.

Dass ich unter Umständen von zwei Stellen gleichzeitig auf das Cluster zugreife, habe ich zugegebenermaßen nicht bedacht. Wenn ich dich richtig verstanden habe, wäre das aber auch bei einer globalen Variable oder FGV problematisch, richtig?
Hallo creo,

Zitat:Da hier auch viele Nachrichten enthalten sind, die mich nicht interessieren, wollte ich in der ersten Schleife nur die Kommunikation laufen lassen und hier die Daten mitschreiben, die für mich bestimmt sind. In der zweiten Schleife werden dann nur noch die Flags im Cluster abgefragt und entsprechend reagiert und hierüber auch auf die einzelnen Messdaten im Array zugegriffen.
Und warum müssen dann beide Schleifen die exakt gleiche Datenstruktur verwenden?
Die erste Schleife filtert nur die CAN-Messages anhand ihrer ArbID. "Gute" Messages werden dann an die zweite Schleife weitergeschickt: sinnvollerweise aber per Queue und nicht per Notifier! (Du willst doch alle "guten" Messages verarbeiten, oder?)
Die zweite Schleife nimmt die Messages entgegen und wertet die enthaltenen Signale aus. Die Signalwerte werden dann in einer anderen Datenstruktur gespeichert…

Zitat:Wenn ich dich richtig verstanden habe, wäre das aber auch bei einer globalen Variable oder FGV problematisch, richtig?
Ja, die Problematik mit RaceConditions tritt auch hier auf.
Bei der FGV hast du zumindest den Vorteil, dass du nur einen zentralen Datenbuffer hast und den Zugriff auf einzelne Elemente darin kapseln kannst.
(18.02.2022 09:29 )GerdW schrieb: [ -> ]Hallo creo,

Zitat:Und warum müssen dann beide Schleifen die exakt gleiche Datenstruktur verwenden?
Die erste Schleife filtert nur die CAN-Messages anhand ihrer ArbID. "Gute" Messages werden dann an die zweite Schleife weitergeschickt: sinnvollerweise aber per Queue und nicht per Notifier! (Du willst doch alle "guten" Messages verarbeiten, oder?)
Die zweite Schleife nimmt die Messages entgegen und wertet die enthaltenen Signale aus. Die Signalwerte werden dann in einer anderen Datenstruktur gespeichert…

[quote]Wenn ich dich richtig verstanden habe, wäre das aber auch bei einer globalen Variable oder FGV problematisch, richtig?
Ja, die Problematik mit RaceConditions tritt auch hier auf.
Bei der FGV hast du zumindest den Vorteil, dass du nur einen zentralen Datenbuffer hast und den Zugriff auf einzelne Elemente darin kapseln kannst.

Um das zu ergänzen: Durch die Benutzung der FGV kannst du garantieren, dass jeder Befehl den du an die FGV schickst atomar ausgeführt wird (daher ganz oder garnicht). Das sorgt zumindest für Datenkonsistenz in deinem Cluster, da verhindert wird, dass an einem Wert zuerst der eine Prozess zuerst zum Zuge kommt und dann der andere, bei der anderen umgekehrt.
Beispiel wie sowas zu Problemen führen kann:

A und B wollen dir Geld überweisen. Jede Überweisung besteht aus Lesen deines IST Kontostands und anschließendem erhöhen um den Überweisungsbetrag. Wenn alles gut geht sieht das so aus:
A lesen, A rechnen, A schreiben, B lesen, B rechnen, B schreiben.
Ist die Leseschreiboperation aber nicht atomar, dann kann als eine Variante das passieren:
A lesen, A rechnen, B lesen, A schreiben, B rechnen, B schreiben
Du verlierst dadurch die Gutschrift von A, das Geld wird bei A aber trotzdem abgezogen (hier kommt es ja nicht zum "Konflikt" bei der Ausführung). Das führt zu einem inkonsistenten Zustand (das Geld das vorher da war ist weder bei A noch bei dir).
Klassische Racingcondition. Machst du jedoch die Schreib-Lese-Operation über eine FGV atomar (ergo die wird in einer Ausführung der FGV abgearbeitet), dann vermeidest du diese Racingcondition zumindest dahingehend, dass dir egal ist welche Überweisung zuerst abgearbeitet wird. Du gewinnst dadurch möglichst schnelle Nebenläufigkeit, bei Verhinderung schädlicher Racing Conditions.
Das Spielchen kannst du im Prinzip so weit treiben, dass du über die FGV Schreib-/Lesesperren verwaltest und dadurch (Auswirkungen von) Racing Conditions weitgehend ausschalten kannst. Im Prinzip also auch für parallele Abarbeitung ein mächtiges Werkzeug.

Die zweite Variante Racing condition ist, dass deine Verarbeitungsschleife nicht schnell genug ist um alle ankommenden schnell genug zu verarbeiten. Das kannst du über eine Queue besser puffern (da du eine größe Vorgeben kannst). Damit fängst du das Problem aber nur ab wenn die Mittlere Ausführungszeit hoch genug ist um alles abzuarbeiten. Ist die Ausführungszeit zu niedrig läuft dir auch die Queue irgendwann voll, oder bei nicht eingeschränkter Größe der Queue crasht dein Programm irgendwann weil dir der RAM ausgeht. Vorher wirds dann noch langsam weil du anfängst ständig in die Auslagerungsdatei zu schreiben.
Referenz-URLs