Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
Hi Leute, bin mal wieder da war aber nie wirklich weg .
Ich sitze mal wieder an der Auslese unserer Maschine und möchte das Programm wieder bissel schlanker machen. Es ist noch nicht komplett und ich habe aktuell nur eine Testversion erstellt. Welche ich in den Anhang packe.
Jetzt zu meinen Problem.
Wenn ich das Programm starte und es längere Zeit(ca.15h) laufen lasse wird das Programm langsam und die Zeitanzeige springt teilweise um 2 Sekunden. Allerdings ist das die Systemzeit und die sollte recht genau laufen, oder liege ich das falsch ?
Ich verwende ein sekündlich wachsendes 2D-Array mit einem Shift-Register in einer While-Loop. So wie ich gelesen habe ist das verwenden eines Arrays nicht ganz trivial, aber ich denke das ist für mich die Lösung. Denn ich würde gerne die Festplattenzugriffe auf ein Minumum beschrenken und gleichzeitig die Programmgröße minimal halten.
Ich habe schon versucht das 2D-Array(19Spalten/maximal 86399((3600s*24h)-1s)Zeilen) innerhalb der While-Schleife zufüllen aber irgenwie bekomme ich das nicht hin. Das hätte den vorteil, dass das wachsende Array nicht immer komplett hin und her Kopiert werden muss. Ich gehe davon aus, dass genau dies zu dem Problem führt. Allerdings fehlt mir offensichtlich das verständnis mit dem Umgang eines Arrays.
Ich hab jetzt schon eine ganze Menge gelesen und auch ein paar Beispiele versucht und versucht zu verstehen, aber irgendwie bekomme ich das nicht hin.
Eswäre super, wenn mir die geballte Kraft des Forums helfen könnte. Ich stehe für Rat und Tat völlig offen.
Dann erstmal vielen Dank.
Grüße aus Mainz
Jürgen
22.11.2016, 08:31 (Dieser Beitrag wurde zuletzt bearbeitet: 22.11.2016 08:33 von GerdW.)
Zitat:Ich verwende ein sekündlich wachsendes 2D-Array mit einem Shift-Register in einer While-Loop.
Das allein ist eine "unverzeihliche" Programmiersünde!
Verschlimmernd kommt hinzu, dass du auch noch ein 2D-Array of Strings verwendest. Und dann noch das ganze mit einer ebenso sekündlichen Neuberechnung deines XY-Graphs kombinierst. Und um das Maß vollzumachen: du verwaltest deine Daten in einem Stringarray und konvertierst dieses wachsende Array in JEDER Iteration erneut in Zahlenwerte, aus denen du dann ein Plotarray für den Graph generierst!
Umständlicher und speicherfressender geht es ja auch kaum…
Vorschläge:
- Wenn du mit Zahlenwerten arbeitest, dann nutze Arrays of DBL!
- Wenn du mit Timestamps arbeitest, dann nutze Timestamps und Timestamp-Arrays!
- Wenn du Timestamps (auf bestimmte Uhrzeiten) vergleichen willst, nutze die "SecondsToDateTime" Funktion!
- Wenn du schon Strings vergleichen willst: Wieso konvertierst du den Timestamp in den String "DD.MM.YYYY HH:MM: SS", wenn du hinterher nur "HH:MM: SS" für den Vergleich benötigst? Warum konvertierst du erst in einen String, um dann diesen String gleich wieder zu parsen? Du scheinst wirklich die Rube-Goldberg-Maschine neu erfinden zu wollen…
- Wenn du Dinge mehrfach ausführst, nutze eine autoindizierende Schleife! Ich verstehe nie, warum Leute ein und dasselbe Code-Fragment gleich 19fach programmieren…
- Schau dir die LabVIEW-Grundlagen an sowie die empfohlenen Programmier"pattern"! Ich empfehle dir das "Producer-Consumer-Schema"!
Hallo Gerd, danke für die schnelle Antwort. Ich versuche mich mal zu erklären wieso ich es so Rube-Goldberg-Mäßig gemact habe.
Zitat:Ich verwende ein sekündlich wachsendes 2D-Array mit einem Shift-Register in einer While-Loop.
Das allein ist eine "unverzeihliche" Programmiersünde!
Verschlimmernd kommt hinzu, dass du auch noch ein 2D-Array of Strings verwendest. Und dann noch das ganze mit einer ebenso sekündlichen Neuberechnung deines XY-Graphs kombinierst. Und um das Maß vollzumachen: du verwaltest deine Daten in einem Stringarray und konvertierst dieses wachsende Array in JEDER Iteration erneut in Zahlenwerte, aus denen du dann ein Plotarray für den Graph generierst!
Ich verwende Strings, da ich so kontrolle über die Nachkommastellen bekomme welche ich in das Spreadsheet geschrieben werden. Und ich keine bessere Lösung gefunden habe die Kontrolle darüber zu haben.
Zitat:Umständlicher und speicherfressender geht es ja auch kaum…
Deswegen habe ich mich ja auch an euch gewand . Weil mir klar war, dass es eine bessere Lösung geben muss. Die mir mit dem geringen Wissen was ich habe aber nicht bewusst wurde.
Zitat:Vorschläge:
- Wenn du mit Zahlenwerten arbeitest, dann nutze Arrays of DBL!
Am Anfang habe ich mit DBL/SGL gearbeitet bin aber auf das hinderniss mit dem Abspeichern des Datums(benötigt 8 Nachkommastellen) und meine Messwerte benötigen nur 2 Nachkommastellen.
Zitat:- Wenn du mit Timestamps arbeitest, dann nutze Timestamps und Timestamp-Arrays!
- Wenn du Timestamps (auf bestimmte Uhrzeiten) vergleichen willst, nutze die "SecondsToDateTime" Funktion!
- Wenn du schon Strings vergleichen willst: Wieso konvertierst du den Timestamp in den String "DD.MM.YYYY HH:MM: SS", wenn du hinterher nur "HH:MM: SS" für den Vergleich benötigst? Warum konvertierst du erst in einen String, um dann diesen String gleich wieder zu parsen? Du scheinst wirklich die Rube-Goldberg-Maschine neu erfinden zu wollen…
Mit Timestamps arbeiten klingt für mich logisch nur hab ich gerade nen hänger wie ich diese mit in das Spreadsheet bekomme, unter berücksichtigung der Nachkommastellen-Problematik.
Das mit dem zu großen String ("DD.MM.YYYY HH:MM: SS") und dann nicht komplett zu verwenden macht natürlich keinen Sinn. Ich dachte mir nur besser haben als brauchen .
Zu Rube-Goldberg muss ich sagen "Einfach kann ja jeder nur ich nicht "
Zitat:- Wenn du Dinge mehrfach ausführst, nutze eine autoindizierende Schleife! Ich verstehe nie, warum Leute ein und dasselbe Code-Fragment gleich 19fach programmieren…
Wenn ich eine einfachere bzw bessere Möglichkeit gesehen hätte, hätte ich diese natürlich auch genutzt. Das Problem was ich mit autoindizierenden Schleifen habe ist, dass ich keine "Live"-Daten zur verwendung in einem Graphen zur Verfügung habe, oder sehe ich das falsch?
Zitat:- Schau dir die LabVIEW-Grundlagen an sowie die empfohlenen Programmier"pattern"! Ich empfehle dir das "Producer-Consumer-Schema"!
Das werde ich mir auf jeden Fall mal anschauen. Ich hab mir hier über die Arbeit auf ein Grundlagenbuch "Einführung in Labview", aber darin bzw dadurch wurde ich nich so schlau.
Alles in allem versuche ich deine Hinweise umzusetzten. Allerdings wäre ich für weitere Hinweise bzw. Hilfestellungen überaus dankbar.
mal etwas Hilfestellung:
Das Umstellen auf DBL-Array darfst du selbst machen!
Zitat:Am Anfang habe ich mit DBL/SGL gearbeitet bin aber auf das hinderniss mit dem Abspeichern des Datums(benötigt 8 Nachkommastellen) und meine Messwerte benötigen nur 2 Nachkommastellen.
Dann verwaltet man die Timestamps in einem 1D-Array und die Messwerte in einem 2D-Array of DBL!
Und die Konvertierung läuft für beide getrennt…
Abgesehen davon: ich finde es sehr irritierend, in einer CSV-Datei Zeitstempel in der Form "3562660550.80100012" gespeichert zu bekommen! Ich bevorzuge da eher Angaben in der Form "22.11.2016 12:56"…
Zitat:Das Problem was ich mit autoindizierenden Schleifen habe ist, dass ich keine "Live"-Daten zur verwendung in einem Graphen zur Verfügung habe, oder sehe ich das falsch?
Ja.
Du holst die Daten aus der exakt selben Quelle - warum solltest du also keine "Live"-Daten haben?
Zitat:aber darin bzw dadurch wurde ich nich so schlau.
Zitat:Das Umstellen auf DBL-Array darfst du selbst machen!
DBL/SGL Umstellung ist erledigt .
Jetzt mal eine Verständisfrage. Und ich oute mich jetzt mal direkt als nixblicker . Wieso bzw. Welchen unterschied mach es denn bei dem Verwenden einen String-Array und einem Double-Array? Ist der Speicherverbrauch deutlich höhre und wenn ja um wie viel?
Zitat:Am Anfang habe ich mit DBL/SGL gearbeitet bin aber auf das hinderniss mit dem Abspeichern des Datums(benötigt 8 Nachkommastellen) und meine Messwerte benötigen nur 2 Nachkommastellen.
Dann verwaltet man die Timestamps in einem 1D-Array und die Messwerte in einem 2D-Array of DBL!
Und die Konvertierung läuft für beide getrennt…
Abgesehen davon: ich finde es sehr irritierend, in einer CSV-Datei Zeitstempel in der Form "3562660550.80100012" gespeichert zu bekommen! Ich bevorzuge da eher Angaben in der Form "22.11.2016 12:56"…
Auch dies hab ich umgestellt. Also keine langen Zahlen mehr sondern im String "DD.MM.YYYY HH:MM: SS%5u"-Format. das %5u ist übertrieben aber sicher ist sicher.
Und auch das Zeit-Array hab ich, wie Du vorgeschlagen hast, in eine eigene Schleife gepackt.
Ich habe es mit einem Timestamp-array innerhalb der Schleife versucht und das klappt natürlich auch aber ich muss sagen, dass mir die Verzögerung, bei einem größeren Datenvolumen, bei Programmstart bissel nerft. Leider verfügt der Rechner auf dem ich es laufen lassen muss mit recht wenig Rechenpower.
Zitat:Das Problem was ich mit autoindizierenden Schleifen habe ist, dass ich keine "Live"-Daten zur verwendung in einem Graphen zur Verfügung habe, oder sehe ich das falsch?
Ja.
Du holst die Daten aus der exakt selben Quelle - warum solltest du also keine "Live"-Daten haben?
Ich habe vorher ein falsches Verständnis dieser Autoindizierung und die Verwenung in einer Schleife gehabt. Ich bin davon ausgegangen, dass man das Programm in einer Schleife laufen lässt und erst wenn die Schleife beendet wird an die Daten ran kommt. Aber die Verwendung wie du es Vorgeschlagen hast ist irgendwie genial. Und das war eine neue Information zum Verwenden einer schleife.
Zitat:aber darin bzw dadurch wurde ich nich so schlau.
Guck dir die Links in meiner Signatur an…
Die Links werde ich mir nach und nach mal zu gemüte führen.
Dürfte ich dich bitten nochmal einen Blick drauf zu werfen mir sagen in welche richtung ich noch Verbesserungspotential im Programm habe?
In deiner ersten Antwort hattest du den Vergleichswirrwar zum Regelmäßigen speichern der Daten angemahnt jetzt ist die Frage ob es so in Ordnung ist oder ob es doch noch einfacher geht. Was die Funktion machen soll ist alle 30Sekunden die Datenspeichern und immer um 0:00Uhr Abspeichern und das Array löschen.
Ach ja "Aufräumen" muss ich das Blockdiagramm auch noch .
Schon mal vielen Dank und noch einen schönen Tag.
Grüße Jürgen
Zitat:Welchen unterschied mach es denn bei dem Verwenden einen String-Array und einem Double-Array? Ist der Speicherverbrauch deutlich höhre und wenn ja um wie viel?
Bei einem Zahlenarray (INT, DBL, ...) arbeitet LabVIEW mit Datenelementen mit bekannter Speichergröße (INT = 4 Bytes, DBL = 8 Bytes) und kann so alle Werte in einem Speicherblock ablegen.
Bei Strings dagegen ist die Größe im Speicher nicht (per se) bekannt, LabVIEW arbeitet deshalb mit einem Pointer auf einen Speicherbereich, der wiederum eine Längenangabe und die eigentlichen Stringdaten enthält. Um nun ein 2D-Array of Strings zu verwalten, muss LabVIEW also ein 2D-Array of Pointers und entsprechend viele (z.T. kleine) Speicherblöcke für jeden einzelnen String verwalten. Das macht die Sache langsam und führt bei kleinen Strings auch zu erhöhtem Speicherbedarf…
Zitat:aber ich muss sagen, dass mir die Verzögerung, bei einem größeren Datenvolumen, bei Programmstart bissel nerft. Leider verfügt der Rechner auf dem ich es laufen lassen muss mit recht wenig Rechenpower.
Es gibt da so einige Programmierkonzepte, um Daten resourcenschonende/-effizienter zu handhaben:
- Consumer-Producer-Struktur
- Queue-driven state machine
Noch was zum Thema Timestamp und ToDateTimeRecord: wenn man UnbundleByName verwendet, hat man die Lesbarkeit des Codes verbessert und kann dazu nur exakt die Elemente auswählen, die man wirklich benötigt!
Zitat:Ach ja "Aufräumen" muss ich das Blockdiagramm auch noch
Ja!
Warum verwendest du 18 einzelne Konstanten im BD statt eines Array mit 18 Elementen? Oder ist das nur zu Demozwecken?
Zitat:Bei einem Zahlenarray (INT, DBL, ...) arbeitet LabVIEW mit Datenelementen mit bekannter Speichergröße (INT = 4 Bytes, DBL = 8 Bytes) und kann so alle Werte in einem Speicherblock ablegen.
Bei Strings dagegen ist die Größe im Speicher nicht (per se) bekannt, LabVIEW arbeitet deshalb mit einem Pointer auf einen Speicherbereich, der wiederum eine Längenangabe und die eigentlichen Stringdaten enthält. Um nun ein 2D-Array of Strings zu verwalten, muss LabVIEW also ein 2D-Array of Pointers und entsprechend viele (z.T. kleine) Speicherblöcke für jeden einzelnen String verwalten. Das macht die Sache langsam und führt bei kleinen Strings auch zu erhöhtem Speicherbedarf…
Das mit den doch recht großen unterschieden im Speicherbedarf recht interessant und erklärt so einiges Ich gehe mal davon aus, dass ein Timestamp ähnlich gehandhabt wird wie ein Zahlenarray sprich auch eine fest Speichergröße verwendet oder ist das eher in richtung String in der "Handhabung"?
Zitat:Es gibt da so einige Programmierkonzepte, um Daten resourcenschonende/-effizienter zu handhaben:
- Consumer-Producer-Struktur
- Queue-driven state machine
Noch was zum Thema Timestamp und ToDateTimeRecord: wenn man UnbundleByName verwendet, hat man die Lesbarkeit des Codes verbessert und kann dazu nur exakt die Elemente auswählen, die man wirklich benötigt!
Zu den Programmier-Konzepte muss ich mich mal einlesen. Vielleicht kann mir das ja irgendwie helfen.
Lustig das du das sagst ich hab eben gerade noch bissel damit "rumgespielt" und hab auch das "Unbundle by Name" versucht und ja das macht es in der Tat einfacher. Wobei ich mit dem Unbundle auch ganz gut zurecht gekommen bin, wahrscheinlich weil ich musste . Aber sehe ich das richtig, dass es zum Vergleichen bestimmter Zeiten 0Sekunden, 30 Sekunden und 0Uhr keine andere Möglichkeit gibt?
Zitat:Warum verwendest du 18 einzelne Konstanten im BD statt eines Array mit 18 Elementen? Oder ist das nur zu Demozwecken?
Ja richtig die Zahlen sind nur zu Demozwecken verwendet. In meinem Fall habe ich drei verschiedene Quellen(DAQ/2xSeriell), die 18 Signale generieren. Ich wollte jetzt erstmal die Daten"erstellung" und Datenspeicherung auf ein minimum reduzieren. Und dann im Nachgang die Quellen hinzufügen.
Ich danke dir vielmals Ohne dich wäre ich wohl aufgeschmissen.
Grüße Jürgen
24.11.2016, 14:46 (Dieser Beitrag wurde zuletzt bearbeitet: 24.11.2016 14:46 von GerdW.)
Zitat:Ich gehe mal davon aus, dass ein Timestamp ähnlich gehandhabt wird wie ein Zahlenarray
Ja. Ein Timestamp belegt immer 128bit=16Byte.
Zitat:Aber sehe ich das richtig, dass es zum Vergleichen bestimmter Zeiten 0Sekunden, 30 Sekunden und 0Uhr keine andere Möglichkeit gibt?
Das hängt von der genauen Fragestellung ab!
1. Du willst "immer bei HH: MM: SS mit SS==0 oder SS==30" speichern: dann musst du eben herausbekommen, wie der Wert für SS ist - und das geht mit ToDateTimeRecord!
2. Du willst "alle 30s" speichern: dann einfach die Schleife im 1s-Takt laufen lassen und alle 30 Iterationen speichern. (Das funktioniert natürlich nur so einfach, wenn die Schleifeniteration nicht wie bei dir immer länger dauern…)
Zitat:Ich gehe mal davon aus, dass ein Timestamp ähnlich gehandhabt wird wie ein Zahlenarray
Ja. Ein Timestamp belegt immer 128bit=16Byte.
Okay ich hab es dann doch umgestellt . Fest Speichergröße gegen mehr oder weniger unbekannte Speicher größe zu tauschen ist wohl den Zeitaufwand beim Starten des Programmes wert .
Zitat:Aber sehe ich das richtig, dass es zum Vergleichen bestimmter Zeiten 0Sekunden, 30 Sekunden und 0Uhr keine andere Möglichkeit gibt?
Das hängt von der genauen Fragestellung ab!
1. Du willst "immer bei HH: MM: SS mit SS==0 oder SS==30" speichern: dann musst du eben herausbekommen, wie der Wert für SS ist - und das geht mit ToDateTimeRecord!
2. Du willst "alle 30s" speichern: dann einfach die Schleife im 1s-Takt laufen lassen und alle 30 Iterationen speichern. (Das funktioniert natürlich nur so einfach, wenn die Schleifeniteration nicht wie bei dir immer länger dauern…)
Ich würde gerne alle 30 Sekunden speichern.
Wie kann ich mir das mit der ToDateTimeRecord vorstellen? So wie ich es aktuell gelöst habe? Oder meinst du das anders? Sorry wenn ich so blöde Fragen stelle.
Und wo du es erwähnt hast, dass mein Programm immer langsamer wird, ist es mir auch aufgefallen. Ich gehe mal davon aus, dass man das nur durch reduzierung des Datenvolumens sprich der Arraygröße ändern kann?!
Ich hätte es zwar gerne meine komplette Auslese in einem Programm, aber irgendwie in bezug auf die Datenkonsistenz keinen Sinn. Lösung also Datenaufzeichnung und Daten"verarbeitung" bzw. Datenanzeige von einander trennen. Und die Datenmenge bei der Aufzeichnung, innerhalb des VI's, so klein wie nötig und so groß wie Möglich halten.
Wie siehst du das? Macht das Sinn? Oder wäre das übertrieben?
So ich denke das wars dann erstmal für diese Woche. Ich wünsche Dir und allen anderen ein schönes Wochenende.
Grüße Jürgen
P.S.: Wenn ich am Wochenende die Muse finde, dann werde ich mich mal an deine Signatur machen. Auch wenn das dann Freizeit wäre und ich nicht dafür bezahlt werde, aber irgendwie ist dsa Thema gerde mega spannend.
Dann musst da aber nicht unbedingt bei SS==0 und SS==30 speichern…
Zitat:Wie kann ich mir das mit der ToDateTimeRecord vorstellen? So wie ich es aktuell gelöst habe?
Ja, mit der Funktion SecondsToDateTime…
Zitat:Ich gehe mal davon aus, dass man das nur durch reduzierung des Datenvolumens sprich der Arraygröße ändern kann?!
Der Punkt ist hier nicht unbedingt die Datenmenge, sondern das ständige Hinzufügen neuer Daten!
Dadurch zwingst du LabVIEW zu ständigen Speicheranforderungen und Datenkopier-Aktionen, was eben immer mehr Zeit in Anspruch nimmt.
Du kannst dein Datenarray auch gleich zu Beginn auf eine feste Größe festlegen und dann neue Daten nur im Array eintragen (per ReplaceArrayElement). Dann bleibt die Arraygröße konstant und die Abarbeitungszeit dafür auch.
Außerdem gibt es ja extra Programmiervorlagen wie das Producer-Consumer-Schema, mit dem man einzelne Prozesse auftrennen kann - hier in Datenerfassung und Datenverwaltung…