Parallel-Programmierung mit bekannten Mitteln

22. Oktober 2008, 11:58 Uhr | Chris Berg
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 3

Steuerungsparallele Programmierung

Ein weiteres Modell, die steuerungsparallele Programmierung (Control-Parallel Programming), trennt die Arbeit eines Programms nach Aufgaben (Tasks) anstelle von Eingaben (Inputs) auf. Als Beispiel diene eine Autofabrik, in der hundert Arbeiter jeweils ein Auto fertigen. Im übertragenen Sinne entspricht dies einem 100-Wege-datenparallelen Algorithmus. Ein steuerungsparalleles Programm wäre dann eine Fabrik mit einer einzigen Fertigungslinie, die aus hundert Stationen besteht, die jeweils mit einem Arbeiter besetzt sind. Die Arbeiter führen dann unterschiedliche Aufgaben (Tasks) durch, die genau einem Hundertstel der gesamten Montagearbeit entsprechen.

passend zum Thema

Bild 2 zeigt das Beispiel einer zweistufigen Implementierung. Eine Fertigungslinie ist im Allgemeinen effizienter, allerdings gibt es eine Grenze, ab der sich die Gesamtaufgabe nicht weiter in kleinere Einzelaufgaben oder Tasks aufteilen lässt. Dies gilt nicht nur für Autos sondern auch für Code, den der Entwickler gerne auf Tausende von Prozessoren verteilen möchte. Dies ist jedoch in parallelen SoC-Architekturen für Consumer-Applikationen mit ihren begrenzten Ressourcen schlecht möglich.

Selbst wenn Parallelverarbeitung nicht in Betracht kommt, unterteilen Softwareentwickler Programme oft in Phasen. Dies vereinfacht einerseits die Programmierung, das Debugging und die Wartung durch Programmierteams, andererseits entlastet es den Befehls- und Cache-Speicher. In vielen Fällen wurde die steuerungsparallele Zerlegung eines Problems bereits auf die Ebene von Tasks verlegt, die das Betriebssystem sehen kann. Der Einzelbefehl »cc« eines Unix-ähnlichen Systems ruft nacheinander einen C-Preprozessor, Compiler, Assembler und Linker auf. Auf einem SMP-Multiprozessor können mehrere dieser Vorgänge gleichzeitig ablaufen, wobei jedes aufeinander folgende Programm den Output der vorherigen Phase als Input nutzt. Dabei werden Dateien, besser aber weiterhin die Software-Pipes verwendet, die schon immer ein Leistungsmerkmal Unixähnlicher Betriebssysteme einschließlich Linux sind.

Verteilte Datenverarbeitung

Falls eine Zerlegung in unabhängig voneinander laufende Tasks nicht bereits stattfand, muss der Entwickler einige Softwareänderungen durchführen, um die Applikationsphasen für das Betriebssystem und die zugrunde liegende Hardware sichtbar zu machen. Dabei müssen die Daten explizit von einer Task zur nächsten weitergereicht werden, sobald deren »Eigentumsrecht « von einer Phase zur nächsten wechselt. Ein Überarbeiten der Algorithmen in den einzelnen Phasen sollte dabei nicht erforderlich sein, wie es bei der datenparallelen Zerlegung der Fall ist. Eine grobe Task-Zerlegung kann über Prozesse erfolgen, die über Dateien, Sockets oder Pipes kommunizieren. Für eine feinere Steuerung kommt ein Posix-Thread-API (pthreads) zum Einsatz, das von zahlreichen Betriebssystemen wie beispielsweise Linux, Microsoft Windows und vielen Echtzeitbetriebssystemen unterstützt wird.

Bild02_af_18.jpg
Bild 2: Steuerungsparalleles Programmiermodell (control parallel)

Komplexe, modulare Multitasking-Embedded-Softwaresysteme weisen oft zufällige, gleichzeitige Zugriffe auf (Bild 3), selbst wenn dies nicht das vorrangige Designziel ist. Das Gesamtziel des Systems kann die Bearbeitung mehrerer Tasks beinhalten, von denen jede eine eindeutige Verantwortung besitzt und auf bestimmte Eingaben reagiert. Ohne ein Timesharing-Betriebssystem müssten diese Tasks jedoch einzeln auf getrennten Prozessoren verarbeitet werden. Auf einem Timesharing-Uniprozessor laufen sie in abwechselnden Zeitintervallen. Auf einem Multiprozessor mit SMP-Betriebssystem können sie gleichzeitig über alle vorhandenen Prozessoren laufen.

Eine andere Form der parallelen Datenverarbeitung ist mittlerweile so allgegenwärtig, dass sie manchmal gar nicht als »parallel« angesehen wird: die verteilte Datenverarbeitung (distributed computing). Client/Server-Modelle sind hier die häufigsten Ansätze und stellen im Wesentlichen eine Form von Control-Flow-Zerlegung dar. Anstatt die gesamte Berechnung selbst durchzuführen, stellt eine Programm-Task die Verbindung her und sendet Arbeitsanweisungen an eine oder mehrere spezielle Tasks in einem System. Diese wiederum sind dazu ausgelegt, bestimmte Tätigkeiten zu übernehmen. Client/Server-Programmierung erfolgt meist über LANs und WANs. Dem gleichen Muster folgt die Kommunikation zwischen Tasks innerhalb eines SMPSoCs. So können unveränderte Client/Server-Binaries über TCP/IP und On-Chipoder Null-»Loopback«-Netzwerkschnittstellen kommunizieren. Noch effizienter sind lokale Kommunikationsprotokolle, die Datenpuffer in Speicher übergeben.

Eine andere Form der parallelen Datenverarbeitung ist mittlerweile so allgegenwärtig, dass sie manchmal gar nicht als »parallel« angesehen wird: die verteilte Datenverarbeitung (distributed computing). Client/Server-Modelle sind hier die häufigsten Ansätze und stellen im Wesentlichen eine Form von Control-Flow-Zerlegung dar. Anstatt die gesamte Berechnung selbst durchzuführen, stellt eine Programm-Task die Verbindung her und sendet Arbeitsanweisungen an eine oder mehrere spezielle Tasks in einem System. Diese wiederum sind dazu ausgelegt, bestimmte Tätigkeiten zu übernehmen. Client/Server-Programmierung erfolgt meist über LANs und WANs. Dem gleichen Muster folgt die Kommunikation zwischen Tasks innerhalb eines SMPSoCs. So können unveränderte Client/Server-Binaries über TCP/IP und On-Chipoder Null-»Loopback«-Netzwerkschnittstellen kommunizieren. Noch effizienter sind lokale Kommunikationsprotokolle, die Datenpuffer in Speicher übergeben.

Bild03_af_19.jpg
Bild 3: Gleichzeitiges Multitasking (concurrent multitasking)

  1. Parallel-Programmierung mit bekannten Mitteln
  2. Parallel-Programmierung mit bekannten Mitteln
  3. Linux bietet SMP
  4. Steuerungsparallele Programmierung

Jetzt kostenfreie Newsletter bestellen!