Multicore-Programmierung

C-Code für die Parallelisierung analysieren

| Autor / Redakteur: Mike Beunder * / Martina Hafner

( Stephanie Hofschlaeger, pixelio.de)

Mit dem Vormarsch von Multicore-Architekturen rückt auch das Thema Parallelisierung von Software wieder in den Mittelpunkt des Interesses. Wo aber sollte man für eine effiziente Parallelisierung ansetzen?

Die Idee ist nicht neu: Ein Ansatz zur Beschleunigung der Programmausführung führt darüber, den Parallelismus auszunutzen, der in einem Programmfluss naturgemäß vorliegt. Wäre es möglich, die Bereiche eines Programms ausfindig zu machen, die parallel ausgeführt werden können, den Programmfluss dementsprechend umzuorganisieren und Hardware bereitzustellen, um jedes parallele Fragment zu hosten, sollte die Gesamtaufgabe in wesentlich kürzerer Zeit erledigt werden.

In der Praxis erweist sich dieses Problem als recht hartnäckig. Für geraume Zeit musste man sich darüber keine großen Gedanken machen, da die Halbleiterindustrie immer mehr Datenverarbeitungsleitung durch schnellere CPU-Taktraten bereitstellte. Diese Ära geht nun dem Ende entgegen. Die Anbieter von Mikroprozessoren nutzen Multicore-Architekturen, um den Datendurchsatz weiter zu erhöhen. Die Verfügbarkeit dieser Hardware-Plattform, auf der parallele Tasks ablaufen können, steigert wieder das Interesse daran, Programmflüsse zu parallelisieren.

Ob sich ein gesamtes sequenzielles Programm in parallel laufende Teile zerlegen lässt, hängt davon ab, ob diese im Rahmen der Programmausführung zueinander in Beziehung stehen. Damit sind die Abhängigkeiten innerhalb eines Programms von Bedeutung. Diese zu verstehen ist bei der Entwicklung einer parallelen Implementierung entscheidend, die ja funktional identisch mit der ursprünglichen sequenziellen Version sein soll.

Das Amdahlsche Gesetz gilt immer noch

Das Amdahlsche Gesetzt besagt, dass die Leistungssteigerung, die durch parallele Datenverarbeitung erzielt werden kann, durch die Programmteile beschränkt wird, die in einer bestimmten Reihenfolge ablaufen müssen. Für n Prozessoren ist die einzige Möglichkeit, das Programm n Mal so schnell laufen zu lassen, das Aufteilen in n voneinander unabhängige Teilstücke gleicher Länge – was fast nie möglich ist. Programmierer müssen sich daher mit einer Geschwindigkeitszunahme zufrieden geben, die etwas weniger als n Mal so schnell ist. Die Herausforderung besteht also darin, diese Geschwindigkeitszunahme zu maximieren.

Bild 1: Eine ungleiche Parallelisierung eines Programms schränkt die erzielbare Geschwindigkeitssteigerung ein
Bild 1: Eine ungleiche Parallelisierung eines Programms schränkt die erzielbare Geschwindigkeitssteigerung ein ( Vector Fabrics)

In einem Programm gibt es Bereiche, deren Performance entscheidend ist, wie auch solche, die weniger kritisch sind. Um die kritischen Teile so schnell wie möglich ablaufen zu lassen setzt es voraus, dass die nicht kritischen Teile beseitigt sind. Alle Anstrengungen beim Parallel-Computing beruhen darauf, vermeidbare Abhängigkeiten zu beseitigen und jene zu bearbeiten, die übrigbleiben.

Die ideale Programmiersprache

Die verwendete Programmiersprache beeinflusst die Analyse des Programms prinzipiell nicht. Eine ideale parallele Programmiersprache würde aber kein Analyse-Tool erfordern – die Abhängigkeiten wären bei der Überprüfung offensichtlich. ANSI C ist von diesem Ideal weit entfernt, jedoch die gängigste Sprache zur Programmierung von Embedded-Systemen. In der Praxis ist das Problem der Parallelisierung von neuem und bereits bestehenden Codes demnach ähnlich.

Threads und Prozesse

Eine Parallelisierung erzeugt einen Programmbereich, der gleichzeitig mit anderen Bereichen ausgeführt werden muss. Ein solcher Bereich kann als Thread oder Prozess implementiert werden. Threads sind einem Prozess untergeordnet und teilen sich einen gemeinsamen Speicherbereich; Prozesse sind vollständig unabhängig.

Ein Multicore-Programm lässt sich als Einzelprozess mit mehreren Threads implementieren oder als Gruppe kleiner Single-Thread-Prozesse in einer asymmetrischen Multiprocessing-Umgebung (AMP), die prozessinterne Kommunikation (IPC) nutzt, um erforderliche Informationen auszutauschen. Eine Kombination aus beiden ist ebenfalls möglich.

Wo für die Parallelisierung ansetzen?

In welchem Bereich sollten die Möglichkeiten für eine parallele Ausführung näher untersucht werden? Auf niedrigster Stufe kann über Parallelismus auf Befehlsebene eine Neuordnung und Parallelisierung von Low-Level-Befehlen stattfinden. Dies hängt jedoch stark von der Architektur des Target-Prozessors ab und wird von Compilern bereits berücksichtigt. Hier ist es schwierig, zusätzliche Vorteile zu erzielen.

Das andere Extrem: Werden sehr große Programmteile untersucht, hängen diese meist immer voneinander ab, sobald die Verarbeitung nicht triviale Bestandteile enthält.

Inhalt des Artikels:

Kommentar zu diesem Artikel abgeben

Schreiben Sie uns hier Ihre Meinung ...
(nicht registrierter User)

Kommentar abschicken
copyright

Dieser Beitrag ist urheberrechtlich geschützt. Sie wollen ihn für Ihre Zwecke verwenden? Infos finden Sie unter www.mycontentfactory.de (ID: 23586410 / Software Engineering)