Multicore-Programmierung mit NI LabVIEW

Überblick

Der grafische Programmieransatz von NI LabVIEW spart nicht nur Entwicklungszeit, sondern bietet auch wichtige Vorteile für die Programmierung mit Multicore-Prozessoren und anderer paralleler Hardware wie z. B. FPGAs. Einer dieser Vorteile ist die Fähigkeit, Anwendungen automatisch auf CPUs mit zwei, vier oder mehr Cores zu skalieren, ohne dass zusätzlicher Programmieraufwand nötig wäre. Durch den grafischen LabVIEW-Code können parallele Operationen zudem visualisiert werden, da LabVIEW dieses häufig eingesetzte Programmiermuster intuitiv darstellt.

Herausforderung der parallelen Programmierung

Parallele Programmierung wird zunehmend zu einer Notwendigkeit, um das volle Potenzial von Multicore-Prozessoren auszunutzen. Aus verschiedenen Gründen, u. a. Stromverbrauch und Speicherbandbreite, können die Taktraten moderner Prozessoren nicht weiter erhöht werden. Stattdessen integrieren CPU-Hersteller nun mehrere Prozessorkerne mit gleichbleibenden oder sogar verringerten Taktfrequenzen auf einem Chip. Das bedeutet, dass nun Anwendungen erstellt werden müssen, die auf Multicore-Prozessoren ausgeführt werden können. Wenn Anwendungen nicht für eine Multicore-Ausführung optimiert werden, kann es zu Leistungseinbußen kommen.

Für diese Herausforderung stehen verschiedene Werkzeuge zur Verfügung, mit denen Programmcodes erstellt werden können, die das volle Potenzial von Multicore-Prozessoren nutzen. Eine Möglichkeit besteht im manuellen Zuweisen von Codeabschnitten auf Threads, die dann vom Betriebssystem auf die verschiedenen Prozessorkerne aufgeteilt werden. Allerdings kann sich die Verwaltung der Threads schwierig und zeitaufwändig gestalten. Zwar abstrahieren einige Programmiersprachen und APIs die Arbeitsschritte mit Threads, aber Anwender müssen trotzdem festlegen, welche Operationen parallel ausgeführt werden sollen.

Figure 1. CPU clock rates have stopped increasing multicore processors are the performance growth area now.

Abbildung 1: CPU-Taktraten werden nicht weiter erhöht, stattdessen sorgen nun Multicore-Prozessoren für Leistungssteigerungen.


Automatische Ausnutzung der Vorteile von Multicore-Prozessoren

Programmierung in LabVIEW bedeutet die Erstellung grafischen Codes (G), der einem Flussdiagramm ähnelt. Dies unterscheidet sich grundlegend von der Programmierung mit traditionellen, sequenziellen Sprachen. Die grafische Programmierung wird auch als Datenflussprogrammierung bezeichnet. Anstelle von Befehlssequenzen, die nacheinander ausgeführt werden, enthält LabVIEW Variablen, die durch Operationen miteinander verbunden werden. Der LabVIEW-Compiler legt dabei automatisch fest, in welcher Reihenfolge Befehle ausgeführt werden, um das gewünschte Ergebnis zu erzielen. Das bedeutet auch, dass in LabVIEW zwei voneinander unabhängige, parallele Codeabschnitte zur gleichen Zeit auf unterschiedlichen Cores des Prozessors ausgeführt werden können.

Dies wird durch das einfache arithmetische Programm in Abbildung 2 verdeutlicht. LabVIEW erkennt, dass sowohl die Multiplizier- und Addierfunktion als auch die Subtrahierfunktion parallel ausgeführt werden können, da sie nicht voneinander abhängen.

Figure 2. Independent code paths can execute simultaneously.

Abbildung 2: Unabhängige Codepfade können simultan ablaufen.

Der LabVIEW-Compiler identifiziert verschiedene parallele Codeabschnitte auf dem Blockdiagramm und weist diese zur Ausführung einer festgelegten Anzahl an Threads zu. Somit ist es nicht notwendig, Threads manuell zu verwalten. Zudem wird verhindert, dass zu viele Threads erstellt werden, was zu Leistungseinbußen führen kann.

 

Manuelle Thread-Erstellung

LabVIEW verwaltet Threads und die Zuweisung auf Multicore-Prozessoren zwar automatisch, bietet jedoch weiterhin die Möglichkeit der manuellen Verwaltung. Es kann z. B. notwendig sein, einen spezifischen Task wie die Überwachung einer Notfallbedingung in einem dedizierten, priorisierten Thread auszuführen. Timing-Strukturen in LabVIEW, wie z. B. die zeitgesteuerte Schleife, erstellen jeweils einen einzelnen Thread, in dem der Code der Struktur ausgeführt wird. Die Threads können über die Option „Zuordnen von Prozessorressourcen“ während der Entwicklungs- wie auch der Ausführungszeit einem spezifischen Prozessorkern zugewiesen werden. Mit LabVIEW können Anwender sich in allererster Linie auf die Lösung von Aufgaben konzentrieren, behalten aber für den Fall der Fälle die Low-Level-Kontrolle.

 

Intuitive Darstellung parallelen Codes

LabVIEW bietet noch einen weiteren wichtigen Vorteil beim Einsatz von Multicore-CPUs: die intuitive grafische Darstellung parallelen Codes. Parallele Programme können zwar auch mit traditionellen, sequenziellen Sprachen erstellt werden, doch ist es häufig eine Herausforderung, den Überblick über parallele Operationen zu behalten. Da Entwickler beim Erstellen umfangreicher Anwendungen häufig in Teams arbeiten, stellt die Dekodierung parallelen Codes, der von anderen geschrieben wurde, häufig eine weitere Schwierigkeit dar.

Im Gegensatz dazu stellt die Datenflussprogrammierung von LabVIEW eine einfache Kommunikationsform dar: das Flussdiagramm. Seit Jahren nutzen sequenzielle Programmierer Flussdiagramme, um einen Überblick über die Programmelemente zu behalten und miteinander zu kommunizieren. Anstatt Flussdiagramme in sequenziellen Code zu übersetzen und umgekehrt, können bei grafischem Code Entwicklungsideen direkt implementiert werden. Zudem können parallele Codepfade, die auf unterschiedlichen Prozessorkernen ausgeführt werden können, schnell identifiziert werden.

Der grafische LabVIEW-Code stellt die gängigsten parallelen Programmiermuster von Industrie und Forschung intuitiv dar. Diese Programmiermuster sind u. a. Task-Parallelität, Datenparallelität und Pipelining.

 

Task-Parallelität

Task-Parallelität bedeutet, dass mindestens zwei separate Operationen parallel ausgeführt werden können. Im untenstehenden LabVIEW-Code ist zu sehen, dass die Filter- und FFT-Operation nicht voneinander abhängig sind und somit simultan auf verschiedenen Prozessorkernen ausgeführt werden können.

Task parallelism

Abbildung 3: Beispiel für Task-Parallelität

 

Datenparallelität

Bei der Datenparallelität handelt es sich um ein gängiges Programmiermuster, bei dem ein großer Datenabschnitt in kleinere Abschnitte aufgeteilt wird, die simultan ablaufen, bevor die Ergebnisse zusammengeführt werden. Im nachfolgenden Code werden die Aufteilung der Datenkanäle, die Verarbeitung und Wiederzusammenführung dargestellt.

Data parallelism

Abbildung 4: Beispiel für Datenparallelität

 

Pipelining

Pipelining ist eine Art Fließband für Operationen, bei dem Funktionen wiederholt durchgeführt und die Daten an die nächste Operation weitergegeben werden. In LabVIEW kann das Pipelining mithilfe von Feedback-Knoten zwischen Operationen dargestellt werden.

Pipelining

Abbildung 5: Beispiel für Pipelining

Ein Großteil realer Anwendungen wie z. B. RF-Signalverarbeitung und Bildanalyse nutzt eine Kombination dieser und anderer paralleler Programmiermuster. So können beispielsweise mehrere Pipelines in ein LabVIEW-Blockdiagramm implementiert werden, die sowohl Task-Parallelität als auch Pipelining repräsentieren. Mithilfe der intuitiven Darstellung des parallelen Codes in LabVIEW können Anwendungen für Multicore-Prozessoren optimiert werden.

 

Leistungsstarke grafische Fehlerbehebungswerkzeuge

Die Fehlerbehebung ist ein wichtiger Bestandteil der Anwendungsentwicklung und LabVIEW bietet sowohl integrierte grafische Fehlerbehebungsfunktionen als auch Anbindungsmöglichkeiten für Add-on-Tools. Mit der Highlight-Funktion in LabVIEW können Anwender sehen, wie Daten zwischen Operationen fließen und paralleler Code simultan ausgeführt wird. Das LabVIEW Desktop Execution Trace Toolkit zeigt zudem die exakte Sequenz der Anwendungsereignisse. Bei LabVIEW-Hardwarezielen, die Echtzeitbetriebssysteme ausführen, zeigt das NI Real-Time Execution Trace Toolkit den vollständigen Programmverlauf der auf den jeweiligen CPU-Cores ausgeführten Threads mit detaillierten Zeitangaben an, sodass Probleme wie Prioritätsumkehrung, bei der ein Task mit höherer Priorität auf die Ausführung eines Tasks mit niedrigerer Priorität warten muss, identifiziert und behoben werden können. Die Möglichkeit, zu sehen, welcher Thread auf welchem Core zu welchem Zeitpunkt und unter Verwendung welcher Ressourcen ausgeführt wird, ermöglicht das Optimieren der Leistung und Zuverlässigkeit.

 

Lösungen für die größten Anwendungsherausforderungen

Zusätzlich zur Programmierung von Multicore-CPUs kann LabVIEW auch mit anderer paralleler Hardware eingesetzt werden, darunter FPGAs, grafische Verarbeitungseinheiten und sogar Computing Clouds. Alle diese Hardwareplattformen haben individuelle Eigenschaften sowie Vor- und Nachteile, jedoch gibt LabVIEW Ingenieuren und Wissenschaftlern genau die richtigen Werkzeuge an die Hand, um die passende Plattform für die jeweilige Anwendungsanforderung optimal zu nutzen. Da LabVIEW mit ganz unterschiedlicher Hardware eingesetzt werden kann, können Anwender die grafische Programmierung für eine große Auswahl von Projekten mit paralleler Verarbeitung nutzen.

Tatsächlich setzen Wissenschaftler, die an den komplexesten Forschungsprojekten der Welt arbeiten – von der Erforschung der Kernfusion bis zum weltgrößten Teleskop – LabVIEW zusammen mit paralleler Hardware ein. LabVIEW wurde dafür konzipiert, Anwender der unterschiedlichsten Branchen dabei zu unterstützen, ihre Ideen in funktionierende Programme umzuwandeln. Da LabVIEW mithilfe des intuitiven grafischen Codes automatisch das volle Potenzial von Multicore-Prozessoren ausschöpft, können Anwender stets die neueste parallele Hardware einsetzen, um sich technischen und wissenschaftlichen Herausforderungen zu stellen.

Nächste Schritte

LabVIEW-Fachbeiträge herunterladen

LabVIEW evaluieren

Webcasts zu NI LabVIEW

Nach oben