06.11.2010, 11:23
(Dieser Beitrag wurde zuletzt bearbeitet: 06.11.2010 11:27 von Matze.)
Beitrag #1
|
Matze
LVF-Team
Beiträge: 1.027
Registriert seit: Apr 2010
20xx
2010
DE_EN
7xxxx
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
Hi zusammen,
ich habe mal wieder eine Real-Time-Frage (cRIO).
Aktuell habe ich eine While-Schleife, in der Datenerfassung, Auswertung und Protokollierung erfolgen. Es handelt sich dabei um mehrere Sensoren, die teils parallel, teils nacheinander eingelesen werden.
Aktuell habe ich das sequenziell so aufgebaut:
1. Datenerfassung aller Sensoren
2. Prüfen, welche Daten relevant sind bzw. welche Sensoren auszuwerten sind
3. Messzeit abwarten
4. Messende: Alle aufgezeichneten Messdaten auf einmal in eine Binärdatei schreiben
Es kann folgendes sein: Messzeit 5 Sekunden und z.B. nach 1 Sekunde beginnt die Messung von Sensor 1, nach 2 weiteren Seunden die von Sensor 2. Wenn die Messung von Sensor 1 dann zu Ende ist und die Daten protokolliert werden, läuft die Messung von Sensor 2 noch weitere 3 Sekunden und wird dann protokolliert. In der Zeit kann aber die Messung von Sensor 1 wieder beginnen.
Mein Problem ist nun, dass das Speichern der Datei sehr lange dauert (ca. 100 - 500 ms), auch wenn das nur ca. 300 Bytes sind.
Die Messwerte vom FPGA werden zwar gepuffert und gehen auch bei Verzögerungen nicht verloren, aber die Messzeit variiert, wenn der Speichervorgang zu lange dauert. Und deterministisch bin ich auch nicht mehr (klar, Dateizugriffe sind es nunmal nicht).
Mit dem Real-Time Execution Trace Toolkit konnte ich sehen, dass das Speichern alles ausbremst.
Ich speichere pro Messung übrigens ein Cluster ab (Messdaten, Bewertungsergebnisse etc).
Nun dachte ich mir, ich nehme eine zeitkritische Schleife für Erfassung und Bewertung und eine parallele While-Schleife, die die Protokollierung übernimmt.
Die Daten gelangen parallel über mehrere RT-FIFOs von der zeitkritischen Schleife in die Datei-I/O-Schleife. Meherere RT-FIFOs deshalb, weil ein RT-FIFO nur einen Datentyp aufnehmen kann, ich aber mehrere habe (2 Dbl-Arrays, 1 boolsches Array, ... pro Sensor).
Die Anzahl der RT-FIFOs ist vermutlich nicht kritisch. Es könnten bis zu ca. 36 sein (mehrere Sensoren, von denen u.U. die Daten gleichzeitig protokolliert werden müssen, wenn das Messende gleichzeitig erreicht ist).
In der zeitkritischen Schleife würde ich z.B. alls 100 ms meine Messwerte aus dem DMA-FIFO (vom FPGA) auslesen und dann auswerten. In der Zeit, in der auf die Messwerte gewartet wird, könnten eventuelle Speichervorgänge in der parallelen Schleife durchgeführt werden. Die zeitkritische Schleife hat natürlich eine höhere Priorität.
Ist dieses Vorgehen sinnvoll oder kennt ihr Alternativen?
Ich glaube, es gibt auch das TDMS-Format im RT-System, nur weiß ich nicht, ob das schneller ist, da auch hier die Datei geöffnet und wieder geschlossen werden muss, was langsam ist. Ich würde die Datei dann wohl beim Messbeginn öffnen, während der Messung streamen und bei Messende schließen. Nur Öffnen und schließen ist garantiert auch langsam.
Über Tipps aus der Praxis, eure Erfahrungen oder Anregungen würde ich mich wirklich freuen.
Grüße
Matze
|
|
|
06.11.2010, 12:01
Beitrag #2
|
jg
CLA & CLED
Beiträge: 15.864
Registriert seit: Jun 2005
20xx / 8.x
1999
EN
Franken...
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
Zwischen den Zeilen lese ich heraus, dass du für dein File-Speichern immer den File öffnest, schreibst und dann wieder schließt. Ist dem so? Das ist natürlich Gift für die Performance. File offen halten!
Gruß, Jens
Wer die erhabene Weisheit der Mathematik tadelt, nährt sich von Verwirrung. (Leonardo da Vinci)
!! BITTE !! stellt mir keine Fragen über PM, dafür ist das Forum da - andere haben vielleicht auch Interesse an der Antwort!
Einführende Links zu LabVIEW, s. GerdWs Signatur.
|
|
|
06.11.2010, 12:13
Beitrag #3
|
Matze
LVF-Team
Beiträge: 1.027
Registriert seit: Apr 2010
20xx
2010
DE_EN
7xxxx
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
Da hast du mich richtig verstanden:
Ich öffne nach dem Messende die Datei, schreibe alle Messwerte hinein und schließe sie dann.
Das ist jedoch die einzige Möglichkeit, wenn nicht alle Messungen in eine einzige, riesige Datei sollen. Pro Messung muss eine separate Datei angelegt werden.
|
|
|
07.11.2010, 16:02
(Dieser Beitrag wurde zuletzt bearbeitet: 21.11.2010 13:57 von rbliomera.)
Beitrag #4
|
rbliomera
LVF-Gelegenheitsschreiber
Beiträge: 56
Registriert seit: Sep 2010
LV X.Y.Z
-
kA
NNNNN
Spain
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
Edit: Deleted. /EOM
|
|
|
07.11.2010, 17:38
(Dieser Beitrag wurde zuletzt bearbeitet: 07.11.2010 17:40 von Matze.)
Beitrag #5
|
Matze
LVF-Team
Beiträge: 1.027
Registriert seit: Apr 2010
20xx
2010
DE_EN
7xxxx
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
' schrieb:File IO würde ich auf jeden Fall in eine dedizierte Schleife verbannen. RT-FIFO ist vermutlich dazu etwas unhandlich. Da kann man zwar auch komplette Cluster mit verschicken, die müssen dann allerdings fixed size sein, also keine Arrays, Strings o.ä. mit drinnen.
Ja, so steht es in der Hilfe. Arrays kann man schon übertragen, sofern die Größe bekannt ist (und das ist sie). Nur dürfen diese nur eindimensional sein und pro RT-FIFO ist nur ein Detentyp zulässig. Daher muss ich mehrere RT-FIFOs verwenden.
' schrieb:Deshalb würde ich es erstmal versuchen mit _einer_ Queue umzusetzen und damit dann deinen Datencluster auf einmal schicken. Keep it simple.
Keep it simple but bad? *g*
Queues sind leider nicht deterministisch, weshalb ich diese nicht einsetzen werde. Das wäre zu schön gewesen, einfach einen Cluster übergeben zu können.
Zuerst dachte ich, dass das mit den RT-FIFOs so geht. Du glaubst gar nicht, wie mich das aufgeregt hat, da nun dynamisch sämtliche Referenzen zu verwalten. Aber das sollte das kleinste Problem sein.
' schrieb:Müssen es denn viele Einzeldateien sein? Mglw. wird es schneller, wenn du einmal eine Binärdatei öffnest und da einfach die Cluster aneinander hängst. Zum Vereinzeln hat die Hostapplikation sicher genug Zeit beim Abholen.
Das Ganze kommt in eine Anlage und sollte über Monate/Jahre zuverlässig laufen. Ich möchte da eine Art Ringspeicher verwenden, sodass ich die letzten 100 Messungen beispielsweise speichere. Kommt eine neue hinzu, lösche ich die alte Messdatei.
D.h. ich muss mehrere Dateien verwenden. Mit einer komme ich da nicht weit.
So habe ich auch leicht die Möglichkeit, die Daten von einer einzelnen Messung per FTP an einen Windows-Rechner zu übertragen.
|
|
|
07.11.2010, 19:43
Beitrag #6
|
jg
CLA & CLED
Beiträge: 15.864
Registriert seit: Jun 2005
20xx / 8.x
1999
EN
Franken...
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
' schrieb:Das Ganze kommt in eine Anlage und sollte über Monate/Jahre zuverlässig laufen. Ich möchte da eine Art Ringspeicher verwenden, sodass ich die letzten 100 Messungen beispielsweise speichere. Kommt eine neue hinzu, lösche ich die alte Messdatei.
D.h. ich muss mehrere Dateien verwenden. Mit einer komme ich da nicht weit.
So habe ich auch leicht die Möglichkeit, die Daten von einer einzelnen Messung per FTP an einen Windows-Rechner zu übertragen.
Mal eine Idee: Sind die Cluster, die du binär in Files abspeicherst, immer gleich groß? Dann könntest du den Ringspeicher nämlich auch mit einem File machen.
Die Grundidee: Du errechnest dir auf Grund eines Zählers immer die Position, an die du Infos in den Ringspeicherfile schreiben willst. Genau da überschreibst du dann binär die entsprechenden Bytes.
Damit könntest du die File-Refnum immer offen halten, und hättest auch nur einen File.
Ich habe sowas schon programmiert, geht echt gut!
Gruß, Jens
Wer die erhabene Weisheit der Mathematik tadelt, nährt sich von Verwirrung. (Leonardo da Vinci)
!! BITTE !! stellt mir keine Fragen über PM, dafür ist das Forum da - andere haben vielleicht auch Interesse an der Antwort!
Einführende Links zu LabVIEW, s. GerdWs Signatur.
|
|
|
07.11.2010, 21:08
(Dieser Beitrag wurde zuletzt bearbeitet: 21.11.2010 13:56 von rbliomera.)
Beitrag #7
|
rbliomera
LVF-Gelegenheitsschreiber
Beiträge: 56
Registriert seit: Sep 2010
LV X.Y.Z
-
kA
NNNNN
Spain
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
Edit: Deleted. /EOM
|
|
|
07.11.2010, 21:42
Beitrag #8
|
Matze
LVF-Team
Beiträge: 1.027
Registriert seit: Apr 2010
20xx
2010
DE_EN
7xxxx
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
Hallo ihr beiden,
danke für eure wirklich interessanten Antworten.
@Jens: Das klingt sehr interessant und die Größe der Daten müsste immer gleich sein. Das sind einzelne boolsche Werte und Arrays, deren Länge ich von vornherein fest vorgebe (damit nicht laufend neu Speicher zugewiesen wird). Daher müsste das gehen.
Hast du mir da einen kleinen Code-Schnippsel, damit ich mir angucken kann, wie du das meinst?
Die Dateiposition beim neuen Element ans Ende setzen und wie lösche ich dann die ersten x Bytes oder kann ich da etwas wie "SizeOf(MeinCLuster)" übergeben, um das SubVI allgemein zu halten?
Was bei der Lösung natürlich kompliziert wird, ist das Auslesen:
Ich schreibe z.B. Messung 1 von Sensor 1 in die Datei, dann Messung 1 von Sensor 2, dann Messung 2 von Sensor 1 und dann Messung 2 von Sensor 3 etc. und muss das möglichst wieder auseinander fummeln können.
Bei einzelnen Dateien kann ich da wunderbar pro Sensor ein Verzeichnis anlegen (oder pro Messung) und dort die Dateien organisieren. Anders bräuchte ich vermutlich einen Header pro Eintrag.
' schrieb:Wie groß darf denn dein Jitter sein auf der Sendeseite?
Ein Schleifendurchlauf dauert vielleicht 20 - 30 ms und das sollte eben alles im Rahmen sein. Also eine Unterbrechung von 100 ms wäre dort nicht gut. Daher wollte ich das auslagern und in der Ruhephase der zeitkritischen Schleife durchführen.
' schrieb:Ich weiss das du auf keinen Fall da 'ne Queue nehmen wirst, deshalb an dieser Stelle nur viel Erfolg beim implentieren deines RT-FIFO Ansatzes mit vielen Schreibern und Lesern (und kleinerem Jitter). Ich bin mir sicher das geht, aber ob es den Aufwand tatsächlich Wert ist?
Wenn ich keinen Denkfehler gemacht habe ist das nun einfach und ordentlich gelöst. Ich habe ein SubVI, das mir die Referenzen erstellt, eines, das Daten hineinschreibt, eines, das sie ausliest und eines, das sie am Ende schließt (falls es mal ein Programmende geben sollte).
Das Ganze ist dynamisch (For-Schleifen) und als Eingänge habe ich diverse Arrays/Werte, die je nach Anzahl entsprechende Referenzen anlegen. Die Anzahl ändert sich im laufenden Betrieb zwar nicht, aber so bin ich für zukünftige Projekte gerüstet.
Aber ob das funktioniert, wird sich hoffentlich morgen zeigen.
Wenn die SubVIs so funktionieren, wie ich mir das vorstelle, muss ich mich auch nicht mehr um die unterschiedlichen Datentypen kümmern. Ich gebe denen ein Cluster vor und der wird dann intern auf die verschiedenen RT-FIFOs aufgeteilt.
Aber Theorie und Praxis sind 2 paar Stiefel. Ich bin selbst gespannt.
' schrieb:Du wolltest ja Tips aus der Praxis... und in der Praxis habe ich schon cRIO Projekte mit RT-FIFOs und Queues auch im Mischbetrieb gesehen, die laufen wie 'ne eins. Mit mehreren TimedLoops und recht harten Echtzeitanforderungen.
Das glaube ich dir gerne, aber sobald größere Daten an die Queues übergeben werden (Messreihen), kann das zu einem recht hohen Jitter führen, denke ich. Vor allem dann, wenn versucht wird, gleichzeitig lesend und schreibend auf die Queue zuzugreifen. Kann man das ausschließen (ich kann's nicht), sind die Queues sicherlich problemlos einsetzbar oder halt bei kleinen Datenmengen.
Wenn ich das mit den RT-FIFOs nicht gebacken bekomme, werde ich den Einsatz von Queues versuchen, aber da bleibt mir dann immer ein etwas mulmiges Gefühl, muss ich zugeben. Doch es ist interessant zu hören, dass ihr das so ensetzt.
Habt ihr da auch große Datenmengen, die ihr in den Queues transportiert oder sind das nur z.B. boolsche Werte um eine bestimmte Aktion daraufhin ausführen zu können ("MessendeErreicht" oder sowas)?
' schrieb:Wenn es irgendwie geht, würde ich versuchen von einem Filebased Ringpuffer weg zu kommen (ggf. die Requirements dazu nochmal hinterfragen). Die SSDs sind zwar inzwischen super robust, aber darauf anlegen würde ich es trotzdem nicht. Also das Ganze RAMbased und entweder nur recht selten Schreiben oder komplett nur auf Anforderung des Hosts.
Da gebe ich dir Recht, nur ist das für uns nicht praktikabel. Das cRIO muss Daten loggen und wenn man später sieht, dass eine Messung schlecht war, muss man nachträglich auf die Daten zurückgreifen können.
Später werden wahrscheinlich nur die Messungen protokolliert, die fehlerhaft waren und die sollten nach Möglichkeit gegen Null gehen (Null ist natürlich unrealistisch), aber es werden dann wohl verhältnismäßig wenig Daten geschrieben. Nur im Worstcase-Fall (alle Messungen laufen gleichzeitig, sind gleichzeitig beendet und alle fehlerhaft (Teil n.i.O), soll das Programm weiter laufen.
|
|
|
09.11.2010, 09:15
Beitrag #9
|
jg
CLA & CLED
Beiträge: 15.864
Registriert seit: Jun 2005
20xx / 8.x
1999
EN
Franken...
Deutschland
|
Datei-I/O bei LV-Real-Time (Prioritäten, ...)
' schrieb:@Jens: Das klingt sehr interessant und die Größe der Daten müsste immer gleich sein. Das sind einzelne boolsche Werte und Arrays, deren Länge ich von vornherein fest vorgebe (damit nicht laufend neu Speicher zugewiesen wird). Daher müsste das gehen.
Hast du mir da einen kleinen Code-Schnippsel, damit ich mir angucken kann, wie du das meinst?
Die Dateiposition beim neuen Element ans Ende setzen und wie lösche ich dann die ersten x Bytes oder kann ich da etwas wie "SizeOf(MeinCLuster)" übergeben, um das SubVI allgemein zu halten?
Was bei der Lösung natürlich kompliziert wird, ist das Auslesen:
Ich schreibe z.B. Messung 1 von Sensor 1 in die Datei, dann Messung 1 von Sensor 2, dann Messung 2 von Sensor 1 und dann Messung 2 von Sensor 3 etc. und muss das möglichst wieder auseinander fummeln können.
Nein, auf die Schnelle habe ich keinen Codeschnipsel. (das was ich hätte, ist aus einem Firmenprojekt, kann ich hier nicht hochladen).
Im Prinzip geht es aber um einen Ringspeicher, genauso wie du ihn per Schieberegister erzeugst. Wenn dein Ringspeicher z.B. 10 Element groß ist, dann schreibst du im ersten Schritt in Element 1, im zweiten in Element 2, ..., im zehnten in Element 10, im elften wieder in Element 1, usw usw.
Also keine Bytes des File löschen und hinten anhängen, sondern immer mit der Filerefnum auf eine bestimmte Speicher-Stelle im File zeigen und dort gezielt Bytes überschreiben. Und wenn du an der letzten Speicherstelle angekommen bist, fängst du wieder von vorne an. Deshalb funktioniert das auch nur, wenn alle "Speicherelemente" gleich groß sind.
Welches Element jetzt zu welcher Messung und zu welchem Sensor gehört, das könnte man sicher auch in das "Speicher-Element" mit rein codieren.
Gruß, Jens
Wer die erhabene Weisheit der Mathematik tadelt, nährt sich von Verwirrung. (Leonardo da Vinci)
!! BITTE !! stellt mir keine Fragen über PM, dafür ist das Forum da - andere haben vielleicht auch Interesse an der Antwort!
Einführende Links zu LabVIEW, s. GerdWs Signatur.
|
|
|
| |