VI-Ausführungsgeschwindigkeit
- Aktualisiert2025-08-27
- 12 Minute(n) Lesezeit
Obwohl LabVIEW VIs kompiliert und Code erstellt, der in der Regel sehr schnell ausgeführt werden kann, ist eine bestmögliche Leistung bei der Arbeit mit zeitkritischen VIs immer oberstes Ziel. In diesem Abschnitt werden einige Einflussfaktoren der Ausführungsgeschwindigkeit erläutert und Programmiertechniken beschrieben, mit denen die bestmögliche Leistung erzielt werden kann.
Untersuchen Sie folgende Komponenten, um die Ursachen für eine langsame Ausführungsgeschwindigkeit zu isolieren:
- Eingabe/Ausgabe (Dateien, GPIB, Datenerfassung, Netzwerk)
- Bildschirmanzeige (große und überlappende Bedienelemente, zu viele Anzeigen)
- Speichermanagement (ineffiziente Nutzung von Arrays und Strings, ineffiziente Datenstrukturen)
- Compiler-Optimierung (Compiler-Einstellungen, die die Reaktionszeit des Editors gegenüber der Ausführungsgeschwindigkeit des VIs abwägen)
Andere Faktoren (z. B. Ausführungsdauer, Dauer von SubVI-Aufrufen) wirken sich normalerweise kaum auf die Ausführungsgeschwindigkeit aus.
Eingabe/Ausgabe
Aufrufe für die Ein- und Ausgabe (I/O) sind meistens sehr zeitaufwändig. Oft beanspruchen diese Aufrufe mehr Zeit als eine Rechenoperation. So werden beispielsweise für einen einfachen Lesevorgang von einem seriellen Port einige Millisekunden benötigt. Dieser Zeitverlust tritt in jeder Anwendung mit seriellen Ports auf, da Daten bei I/O-Aufrufen über mehrere Schichten eines Betriebssystems hinweg übertragen werden.
Ein hoher Zeitverlust lässt sich am besten vermeiden, indem Sie die Anzahl der I/O-Aufrufe auf ein Mindestmaß einschränken. Die Ausführungseffizienz kann verbessert werden, indem mit jedem Aufruf eine große Datenmenge übertragen wird, statt die Datenübertragung auf mehrere Aufrufe zu verteilen.
Sie haben beispielsweise beim Erstellen eines Datenerfassungs-VIs (mit NI-DAQmx) zwei Möglichkeiten für das Lesen von Daten. Sie können eine Funktion zur Übertragung von Einzelwerten verwenden, wie das VI "AI-Kanal abtasten", oder eine Funktion zur Übertragung mehrerer Werte, wie das VI "AI-Signalverlauf erfassen". Wenn Sie 100 Werte erfassen möchten, sollten Sie das VI "AI-Kanal abtasten" in einer Schleife ausführen, wobei die zeitliche Steuerung durch eine Wartefunktion realisiert wird. Sie können auch das VI "AI-Signalverlauf erfassen" verwenden und an dessen Eingang angeben, dass 100 Werte erfasst werden sollen.
Mit dem VI "AI-Signalverlauf erfassen" werden höhere und genauere Sample-Raten erreicht, da das Sampling der Werte mit Hilfe von Hardware-Timern erfolgt. Hinzu kommt, dass der Zeitaufwand für dieses VI ungefähr genauso groß ist wie der Zeitaufwand für den Aufruf des VIs "AI-Kanal abtasten", obwohl eine sehr viel größere Datenmenge übertragen wird.
Bildschirmanzeige
Der größte Zeitverlust in einer Anwendung kann durch häufiges Aktualisieren von Frontpanel-Elementen hervorgerufen werden. Das trifft besonders auf komplexere Anzeigen wie Graphen und Diagramme zu. Der Inhalt von Graphen und Diagrammen wird im Gegensatz zu den meisten Anzeigeelementen periodisch neu dargestellt, egal ob die empfangenen Werte mit den vorherigen übereinstimmen oder nicht. Um eine zu häufige Aktualisierung zu vermeiden, sollten so wenig wie möglich Frontpanel-Elemente verwendet und Frontpanel-Anzeigen möglichst einfach gehalten werden. Bei Graphen und Diagrammen können Sie die Optionen für automatische Skalierung, Achsenteilung, Kantenglättung und Gitter für schnellere Anzeigen deaktivieren.
Wie auch bei anderen I/O-Arten ist die Anzeige eines Elements mit einem gewissen festen Zeitaufwand verbunden. Mit bestimmten Elementen, z. B. Diagrammen, können Sie mehrere Werte gleichzeitig an ein Anzeigeelement weiterleiten. Sie können die Anzahl an Diagrammaktualisierungen durch die Weiterleitung größerer Datenmengen minimieren. Die Datenanzeigeraten sind sehr viel höher, wenn Sie Ihre Diagrammdaten zur gleichzeitigen Anzeige mehrerer Punkte in Arrays zusammenfassen, anstatt jeden einzelnen Punkt bei Empfang anzuzeigen.
Wenn Sie SubVIs erstellen, deren Frontpanels während der Anzeige geschlossen sind, müssen Sie sich keine Gedanken über den Zeitverlust durch die Anzeige machen. Bei geschlossenem Frontpanel vergeht keine Zeit für die Aktualisierung von Elementen, d. h. Graphen sind nicht aufwändiger als Arrays.
Bei multithreadfähigen Systemen können Sie im Kontextmenü unter Fortgeschritten»Synchrone Anzeige auswählen, ob Wertänderungen an Bedien- und Anzeigeelementen sofort oder verzögert angezeigt werden sollen. Standardmäßig wird für Bedien- und Anzeigeelemente die asynchrone Anzeige verwendet. Das heißt, nachdem das Ausführungssystem Daten an die Frontpanel-Elemente weitergegeben hat, kann es die Ausführung unmittelbar fortsetzen. Etwas später erkennt die Benutzeroberfläche, dass die Bedien- und Anzeigeelemente aktualisiert werden müssen, und stellt die Elemente neu dar. Wenn das Ausführungssystem versucht, Elemente mehrere Male kurz hintereinander zu aktualisieren, sehen Sie eventuell nicht alle Aktualisierungen.
Bei den meisten Anwendungen wird die Ausführung durch asynchrone Anzeigen erheblich beschleunigt – ohne Einfluss darauf, was der Benutzer sieht. So kann ein boolescher Wert theoretisch mehrere Hundert Mal pro Sekunde aktualisiert werden, was für das menschliche Auge jedoch ohnehin nicht sichtbar wäre. Durch die asynchrone Anzeige hat das Ausführungssystem mehr Zeit für das Ausführen der VIs. Aktualisierungsraten werden automatisch vom Thread der Benutzeroberfläche reduziert.
Wenn Sie synchrone Anzeigen bevorzugen, klicken Sie mit der rechten Maustaste auf das entsprechende Element und wählen Sie die Option Fortgeschritten»Synchrone Anzeige aus dem Kontextmenü.
Sie können auch die Eigenschaft Panel-Aktualisierungen verzögern wählen, um Frontpanel-Aktualisierungen zu verschieben.
Bildschirmeinstellungen und in das Frontpanel eingefügte Elemente können auch die Leistung eines VIs verbessern. Wählen Sie geringere Werte für Farbtiefe und Auflösung Ihres Bildschirms und aktivieren Sie Hardwarebeschleunigung. Weitere Informationen zur Hardwarebeschleunigung finden Sie in der Dokumentation Ihres Betriebssystems. Auch die Verwendung von Elementen der Palette Klassisch anstelle von Elementen der Palette Modern verbessert die Leistung eines VIs.
Speicherverwaltung
Ziehen Sie folgende Vorschläge in Erwägung, um den Speicher in einem VI für eine optimale Ausführungsgeschwindigkeit zu optimieren.
- Vermeiden Sie das ständige Ändern der Datengröße, so dass keine Kopien der Daten erstellt werden müssen.
- Zum Vermeiden von überflüssigen Datenkopien können Sie auch effektive Datenstrukturen mit einfach zu bearbeitenden Datentypen entwickeln.
- Speichern Sie VIs in der aktuellen Version von LabVIEW, ohne den Programmcode getrennt zu kompilieren.
Compiler-Optimierung
Zur Verbesserung der Reaktionszeit des Editors bei großen VIs schränkt der LabVIEW-Compiler Optimierungen zur Erhöhung der Ausführungsgeschwindigkeit dieser VIs ein. Nach dem Beenden der Entwicklung von großen VIs können Sie LabVIEW zum Priorisieren der Ausführungsgeschwindigkeit gegenüber der Editor-Reaktionszeit konfigurieren. Sie können LabVIEW auch so konfigurieren, dass eine vollständige Compiler-Optimierung für eine gesamte Build-Spezifikation erfolgt.
Weiterleitung von Daten innerhalb einer Anwendung
Sie können zwischen mehreren Verfahren zum Weiterleiten von Daten in einer LabVIEW-Anwendung auswählen. Die folgende Liste zeigt die gängigsten Methoden, geordnet nach Effizienz.
- Verbindungen—Verbindungen dienen zum Weiterleiten von Daten auf die möglichst effiziente Art und Weise. In einer datenflussorientierten Programmiersprache ist die Übertragung von Daten über Verbindungen die schnellste Methode zum Datenaustausch, da es nur eine Datenquelle und eine oder mehrere Datensenken gibt.
- Rückkopplungsknoten—Mit Hilfe eines Rückkopplungsknotens lassen sich Daten aus einem vorhergehenden VI oder einer vorhergehenden Schleifenausführung speichern. Ein Rückkopplungsknoten wird automatisch angezeigt, wenn Sie den Ausgang eines SubVIs, einer Funktion oder einer Gruppe von SubVIs oder Funktionen mit dem Eingang desselben VIs oder derselben Gruppe verbinden und die Option Rückkopplungsknoten automatisch in Schleifen einfügen auf der Seite Blockdiagramm im Dialogfeld Optionen aktiviert ist. Die Option Rückkopplungsknoten automatisch in Schleifen einfügen ist per Standardeinstellung aktiviert. Rückkopplungsknoten speichern Daten der letzten Ausführung von VIs, Funktionen oder Gruppen und können diese Daten an die nächste Ausführung weiterleiten oder einen neuen Initialisierungswert festlegen (je nachdem, ob der Initialisierungsanschluss verschoben wurde). Schieberegister in Schleifen speichern Daten auf die gleiche Weise wie Rückkopplungsknoten, allerdings sind hier durch die Schleife führende Verbindungen erforderlich.
- Schieberegister—Mit Schieberegistern können Sie Daten speichern oder eine Schleife rückkoppeln. Bei Schieberegistern werden Daten durch eine Datenquelle und -senke außerhalb der Schleife und eine Datenquelle und -senke innerhalb der Schleife geleitet. Aufgrund dieses sehr eng gefassten Datenzugriffs wird die Effizienz von LabVIEW maximiert. Schieberegister können durch einen Rückkopplungsknoten ersetzt werden, da dadurch die Verbindungen durch die Schleife entfallen.
- Globale Variablen und funktionale globale Variablen – Verwenden Sie globale Variablen für einfache Daten und einfachen Zugriff. Bei größeren oder komplexeren Datenmengen liest eine globale Variable alle Daten und leitet diese weiter. Verwenden Sie funktionale globale Variablen zur Steuerung der Datenmenge, die ausgegeben werden soll.
Verwendung von Elementen, Elementreferenzen und Eigenschaftsknoten als Variablen
Auch wenn Daten mit Hilfe von Elementen, Elementreferenzen und Eigenschaftsknoten zwischen VIs ausgetauscht werden können, sind diese Komponenten nicht als Variablen gedacht, da sie über die Benutzerschnittstelle arbeiten. Verwenden Sie lokale Variablen und die Eigenschaft "Wert" nur für Benutzeraktionen und das Stoppen paralleler Schleifen.
Die Ausführung von Benutzeraktionen ist seit jeher langsam an Computern. LabVIEW leitet einen Wert doppelter Genauigkeit über eine Verbindung in Nanosekunden weiter und baut Text in Hunderten von Mikro- bzw. Millisekunden auf. So leitet LabVIEW beispielsweise ein 100K-Array über eine Verbindung innerhalb weniger Mikrosekunden weiter. Die Zeit zum Darstellen des dazugehörigen Graphen liegt im zweistelligen Millisekundenbereich. Da Elemente je nach Bedienvorgang ihre Einstellung wechseln, müssen Elemente nach jedem Bedienschritt neu dargestellt werden. Dadurch wird mehr Speicher benötigt und die Leistung gemindert. Sind die Elemente versteckt, kann LabVIEW Daten schneller weiterleiten. Da das Element aber jederzeit angezeigt werden kann, muss LabVIEW nach wie vor das Element aktualisieren.
Wie Multithreading Benutzeraktionen beeinflusst
Die Ausführung von Benutzeraktionen beansprucht mehr Speicher, da LabVIEW vom Ausführungs-Thread zum Thread der Benutzerschnittstelle wechselt. Wenn Sie beispielsweise die Eigenschaft "Wert" festlegen, simuliert LabVIEW einen Benutzer, der den Wert eines Elements ändert. Dabei wird der Ausführungs-Thread angehalten und in den Thread der Benutzerschnittstelle gewechselt, so dass der Wert geändert werden kann. LabVIEW aktualisiert dann den Betriebspuffer, in dem die Daten des Elements gespeichert werden, und stellt das Element neu dar, sofern das Frontpanel geöffnet ist. Anschließend sendet LabVIEW die Daten zurück in einen geschützten Bereich des Speichers, den sogenannten Übertragungspuffer, im Ausführungs-Thread. Dann wechselt LabVIEW zurück in den Ausführungs-Thread. Liest der Ausführungs-Thread das Element erneut aus, so findet LabVIEW die Daten im Übertragungspuffer und empfängt den neuen Wert für den Ausführungspuffer, der Daten im Blockdiagramm speichert.
Wenn Sie in eine lokale oder globale Variable schreiben, wechselt LabVIEW nicht unmittelbar zum Thread der Benutzeroberfläche. Stattdessen schreibt LabVIEW den Wert in den Übertragungspuffer. Die Benutzeroberfläche wird bei der nächsten geplanten Aktualisierung aktualisiert. Eine Variable kann auch mehrmals aktualisiert werden, bevor ein Einzel-Thread-Wechsel oder eine Aktualisierung der Benutzeroberfläche stattfindet. Dies ist möglich, weil Variablen ausschließlich im Ausführungs-Thread arbeiten.
Funktionale globale Variablen können effizienter als herkömmliche globale Variablen sein, da sie keine Übertragungspuffer verwenden. Funktionale globale Variablen gibt es nur im Ausführungs-Thread. Sie benötigen nur einen Übertragungspuffer, wenn ihre Werte auf einem geöffneten Frontpanel angezeigt werden.
Parallele Blockdiagramme
Werden mehrere Blockdiagramme parallel ausgeführt, so wechselt das Ausführungssystem regelmäßig zwischen den Diagrammen. Wenn einige der Schleifen weniger wichtig sind als andere, sollten Sie ihnen mit der Funktion Warten (ms) weniger Zeit gewähren.
Nehmen Sie beispielsweise das folgende Diagramm.
In diesem Diagramm gibt es zwei parallele Schleifen. Eine der Schleifen dient zur Erfassung von Daten und muss so oft wie möglich ausgeführt werden. Die andere Schleife überwacht Benutzereingaben. Aufgrund der Programmstruktur wird beiden Schleifen dieselbe Zeit zugewiesen. Die Schleife für die Überwachung der Benutzeraktionen hat so die Chance, innerhalb einer Sekunde mehrere Male ausgeführt zu werden.
In der Praxis reicht es aber normalerweise aus, wenn die Schleife zur Verarbeitung der Schaltflächenstellung nur einmal pro halbe Sekunde oder seltener ausgeführt wird. Durch Aufruf der Funktion Warten (ms) in der Schleife der Benutzerschnittstelle können Sie der anderen Schleife erheblich mehr Zeit zuweisen.
Parallele Ausführung von For-Schleifen
Die Iterationen von For-Schleifen werden in LabVIEW nacheinander ausgeführt. Bei rechenintensiven For-Schleifen sollten Sie die Iterationen der Schleife zur Verbesserung der Leistung parallel ausführen. Beim parallelen Ausführen von Schleifeniterationen macht sich LabVIEW das Vorhandensein mehrerer Prozessoren zunutze. Parallele Schleifenausführungen müssen jedoch unabhängig von allen anderen Iterationen sein. Mit Hilfe des Dialogfelds Ergebnisse der Suche nach parallel ausführbaren Schleifen können Sie erkennen, welche For-Schleifen sich parallel ausführen lassen. Zum Aktivieren der parallelen Schleifeniterationen klicken Sie mit der rechten Maustaste auf den Rahmen der For-Schleife und wählen Sie Parallele Ausführung von Iterationen konfigurieren aus dem Kontextmenü, um zum Dialogfeld Parallele Ausführung von For-Schleifen-Iterationen zu gelangen.
Nach der Aktivierung der parallelen Ausführung von Schleifeniterationen wird der Anschluss
für parallele Instanzen unter dem Zählanschluss
angezeigt. Mit diesem Anschluss können Sie die Anzahl der Schleifeninstanzen festlegen und erkennen, welche Instanz in einer bestimmten Iteration ausgeführt wird.
Lesen Sie die Hinweise zur Steigerung der Ausführungsgeschwindigkeit, bevor Sie die parallele Ausführung von Schleifeniterationen aktivieren.
Es wird empfohlen, dass Sie in der Fehlerliste eventuelle Warnungen anzeigen, so dass Sie gewarnt werden, wenn die parallele Ausführung von Schleifen zu Problemen in einem VI führt.
SubVI-Overhead
Wenn Sie ein SubVI aufrufen, ist damit ein bestimmter Overhead verbunden. Dieser Overhead ist ziemlich gering (im zweistelligen Mikrosekundenbereich), besonders im Vergleich zum I/O- und Anzeige-Overhead, der im zweistelligen Millisekundenbereich liegen kann. Trotzdem kann sich dieser Overhead in manchen Fällen summieren. Wenn Sie beispielsweise ein SubVI 10.000 Mal in einer Schleife aufrufen, kann der Overhead die Ausführungsgeschwindigkeit bedeutend beeinträchtigen. In diesem Fall ist es ratsam, die Schleife im SubVI einzubetten.
Eine andere Möglichkeit, den SubVI-Overhead zu minimieren, ist die Umwandlung von SubVIs in Unterprogramme. Wählen Sie dazu im Dialogfeld Eigenschaften für VI aus dem Pulldown-Menü Kategorie die Option Ausführen aus und klicken Sie im Pulldown-Menü Priorität auf Unterprogramm. Unterprogramme bringen aber auch Nachteile mit sich. Sie können keine Frontpanel-Daten anzeigen, Timing- oder Dialogfeldfunktionen aufrufen, nach Fehlern suchen, Fehler automatisch behandeln oder Multitasking mit anderen VIs ausführen. Unterprogramme eignen sich in der Regel am besten für VIs, die keine Benutzereingriffe erfordern und kurze, permanent ausgeführte Aufgaben enthalten.
Eine weitere Möglichkeit zum Minimieren von SubVI-Overhead ist das Einfügen von SubVI-Code inline. Beim Inlining wird der kompilierte Code des SubVIs in den kompilierten Code des aufrufenden VIs eingefügt. Wenn Sie Änderungen am SubVI vornehmen, werden alle aufrufenden VIs neu kompiliert, um diese Änderungen zu übernehmen. Prinzipiell wird durch das Inlining vermieden, das SubVI während der Ausführung aufrufen zu müssen. Stattdessen wird der SubVI-Code innerhalb des kompilierten Codes des aufrufenden VIs ausgeführt.
Das Inlining von SubVIs bietet sich insbesondere bei kleinen VIs, SubVIs in Schleifen, SubVIs mit unverbundenen Ausgängen und bei SubVIs mit nur einer Aufrufstelle an. Zum Inlining eines SubVIs aktivieren Sie die Option SubVI inline einfügen auf der Seite Ausführung im Dialogfeld Eigenschaften für VI. Sie müssen außerdem die Ablaufinvariante Ausführung mit vorbelegter Kopie auf derselben Seite des Dialogfelds auswählen. LabVIEW belegt automatisch eine Kopie für jede Instanz vor, wenn der SubVI-Code direkt in das VI eingefügt wird.
Ein SubVI, dessen Code inline in ein VI eingefügt wird, darf nicht über folgende Merkmale verfügen:
- mit Rekursion arbeiten
- automatische Fehlerbehandlung verwenden
- bestimmte Blockdiagrammknoten enthalten, wie z. B. Eigenschaftsknoten und Methodenknoten. Diese Knoten führen bei aktiviertem SubVI-Inlining zu Fehlermeldungen während der Bearbeitung.
- Fehlersuche ermöglichen. Die Fehlersuche muss deaktiviert werden bei SubVIs, deren Code inline eingefügt wird.
- eines der folgenden Arten von VIs sein:
- ein VI mit dynamischer Bindung einer LabVIEW-Klasse
- für CGen oder FPGA bestimmtes VI
- Element-VI - VIs zur Definition eines benutzerdefinierten Bedien- oder Anzeigeelements
- Polymorphes VI
- globales Variablen-VI
- XControl-VI
- Methoden-VI einer XControl-Bibliothek
- VI, das nur in ein Simulationsdiagramm im LabVIEW Control Design and Simulation Module eingefügt werden kann
Selbst wenn das SubVI keines dieser Merkmale aufweist, kann das der SubVI-Code nicht inline in die folgenden Aufrufarten eingefügt werden:
- Dynamische Aufrufe des SubVIs
- Aufrufe des SubVIs, die den Datenbankzugriff aktivieren
Beim Inlining werden alle Einstellungen zu Ausführungspriorität und zur bevorzugten Ausführung ignoriert.
Ein Beispiel dafür, wie die Leistung durch das Inlining von SubVIs optimiert werden kann, finden Sie im VI "Execution Properties.vi" im Verzeichnis examples\Performance\VI Properties.
Umgebungsvariablen-Overhead
Netzwerk-Umgebungsvariablen verursachen einen beträchtlichen CPU- und Speicher-Overhead. Wenn Ihre Anwendung zahlreiche Netzwerk-Umgebungsvariablen enthält, sollten Sie stattdessen die Verwendung der Simple Messaging Reference Library (STM) erwägen. Im Support-Dokument auf ni.com finden Sie weitere Informationen dazu.
Wenn Sie einen kontinuierlichen Daten-Stream von einem Computer auf einen anderen übertragen müssen, verwenden Sie die Funktionen für Netzwerk-Streams.
Unnötige Berechnungen in Schleifen
Vermeiden Sie eine Berechnung in einer Schleife, wenn die Berechnung denselben Wert für jeden Durchlauf ermittelt. Verschieben Sie stattdessen die Berechnung in einen Bereich außerhalb der Schleife und leiten Sie das Ergebnis dann an die Schleife weiter.
Nehmen Sie beispielsweise das folgende Diagramm.
Das Ergebnis der Division ist bei jedem Schleifendurchlauf gleich. Daher können Sie die Leistung steigern, indem Sie die Division aus der Schleife entfernen (siehe folgendes Blockdiagramm).
Sehen Sie sich das nachfolgende Blockdiagramm an.
Wenn Sie wissen, dass der Wert der globalen Variable nicht durch ein anderes simultan laufendes Blockdiagramm oder VI während des Schleifendurchlaufs geändert wird, findet in diesem Diagramm mit dem Lesen aus der und dem Schreiben in die globale Variable bei jeden Schleifendurchlauf eine Zeitverschwendung statt.
Wenn bei dieser Schleife nicht ein anderes Blockdiagramm aus der globalen Variablen lesen bzw. in sie schreiben muss, können Sie auch das folgende Blockdiagramm verwenden.
Beachten Sie, dass das Schieberegister den neuen Wert vom SubVI in den nächsten Schleifendurchlauf übertragen muss. Das folgende Blockdiagramm zeigt einen für einige Anfänger typischen Fehler. Da es kein Schieberegister gibt, werden die Ergebnisse des SubVIs nicht als neue Eingangswerte an das SubVI zurückgeleitet.