Software für Multicore-Systeme entwickeln

Autor / Redakteur: Martin Stockl * / Sebastian Gerstl |

Multiprozess- und Multiprozessor-Applikationen zählen seit vielen Jahren zur Standardausstattung von Embedded Systemen. Dank der parallelen Verarbeitung lassen sich kürzere Reaktionszeiten erreichen und komplexere Aufgaben bewältigen. Was bedeutet das für die Entwicklung und die Architektur von Embedded Systemen?

Anbieter zum Thema

Parallel geht anders: Dank paralleler Verarbeitung lassen sich komplexe Aufgaben schneller erledigen. Multiprozess-Applikationen haben kürzere Reaktionszeiten und bewältigen komplexere Aufgaben. Aber multiple Kerne bedeuten nicht automatisch eine entsprechende Multiplikation der Verarbeitungsgeschwindigkeit. Was bedeutet das für die Entwicklung und die Architektur von Embedded-Systemen?
Parallel geht anders: Dank paralleler Verarbeitung lassen sich komplexe Aufgaben schneller erledigen. Multiprozess-Applikationen haben kürzere Reaktionszeiten und bewältigen komplexere Aufgaben. Aber multiple Kerne bedeuten nicht automatisch eine entsprechende Multiplikation der Verarbeitungsgeschwindigkeit. Was bedeutet das für die Entwicklung und die Architektur von Embedded-Systemen?
(Bild: Clipdealer)

Multiprozessorsysteme sind konzeptionell auf parallele Verarbeitung ausgelegt. Dabei teilen sich die Prozessoren (Cores) gemeinsame Ressourcen, wie Speicher, Peripheriegeräte und Interrupt Controller. Je nach Architektur und Hersteller nutzen heutige Multicore-Prozessoren gemeinsam einen Bus zur Kommunikation mit dem Hauptspeicher und der Peripherie. Speziell wenn verschiedene Betriebssysteme auf den Cores laufen sollen, ist das konfliktfreie Management der gemeinsamen Ressourcen also bereits die erste Herausforderung.

AMP und SMP: Die beiden unterschiedlichen Betriebsmodi bei Multicore

Es gibt zwei unterschiedliche Betriebsarten für Multicore-Systeme. Beim Symmetrischen Multiprocessing (SMP) kontrolliert ein Betriebssystem alle Cores; beim Asymmetrischen Multiprocessing (AMP) läuft auf jedem Core eine eigene Betriebssysteminstanz, wobei dann entweder auf allen Cores das gleiche Betriebssystem (homogenes AMP) läuft oder auf jedem Core ein anderes Betriebssystem (heterogenes AMP).

Der AMP-Modus bietet sich an, wenn die Applikation bereits (wie bei einem Multiprozessorsystem) partitioniert ist oder leicht partitioniert werden kann. Auch sollte der Datenaustausch zwischen beiden Partitionen gering bzw. gut definiert sein. Allerdings benötigt ein System im AMP-Betrieb mehr Speicher. Auch ist das Aufsetzen der Kommunikation zwischen den Cores schwieriger, besonders wenn unterschiedliche Betriebssysteme auf den Cores zum Einsatz kommen.

Zugriff auf gemeinsame Hardware-Ressourcen

Im SMP-Modus ist der Zugriff auf gemeinsame Ressourcen wie Bus und Speicher vereinheitlicht. Aus Entwicklerperspektive setzt die Applikation nur auf einem Betriebssystem auf, welches die Aufgaben gleichmäßig auf die Cores verteilt (Dynamic Load Balancing). Daten können relativ einfach und schnell zwischen den Cores ausgetauscht werden. Allerdings muss das Betriebssystem die Cores verwalten und synchronisieren. Das hat wiederum Auswirkungen auf die Verarbeitungsgeschwindigkeit des Betriebssystems.

Multicore-Programmierung erfordert von den Programmierern darüber hinaus eine neue Herangehensweise. Programme müssen parallelisiert werden, damit die Ausführung sinnvoll von den Kernen geteilt werden kann. Ein objektorientierter Entwicklungsansatz kann hier helfen, da hier die parallele Vorgehensweise bereits im Konzept verankert ist.

Objekte sind autonom ausführbare, gekapselte Einheiten, die im Gesamtsystem mit anderen Objekten kooperieren, um Aufgaben auszuführen. Die Kommunikation mit benachbarten Objekten erfolgt oftmals asynchron über den Austausch von Nachrichten.

Die standardisierte Modellierungssprache Unified Modeling Language (UML) ermöglicht es, in jeder Phase der Softwareentwicklung das zu realisierende Softwaresystem über verschiedene Diagrammformen grafisch zu beschreiben. Beispielsweise können die Entwickler mit Struktur- und Klassendiagrammen die statische Systemarchitektur, mit Zustandsautomaten und Aktivitätsdiagrammen die dynamischen Systemeigenschaften beschreiben. Bemerkenswert dabei ist, dass viele UML-Diagrammtypen von Haus aus Nebenläufigkeiten und Parallelitäten unterstützen und eine entsprechende Syntax zur Verfügung stellen.

Zustandsautomaten und Aktivitätsdiagramme

Bild 1: Parallelität ist integraler Bestandteil der UML und wird von verschiedenen Diagrammen unterstützt, so auch von diesem Zustandsdiagramm
Bild 1: Parallelität ist integraler Bestandteil der UML und wird von verschiedenen Diagrammen unterstützt, so auch von diesem Zustandsdiagramm
(Bild: IBM)

In der Praxis gibt es jedoch oft eine Diskrepanz zwischen dem eigentlichen objektorientierten Entwurf des Systems und seiner Umsetzung im ausführbaren Code, weil die Implementierung paralleler Aktivitäten zu höherem Aufwand für den Austausch von Nachrichten und die Synchronisation führen kann. Entwickler, die moderne UML-Werkzeuge einsetzen, die aus den grafischen UML-Modellen Code generieren und die Kommunikationsmechanismen frei Haus und transparent implementieren, sind hier im Vorteil. IBM Engineering Systems Design Rhapsody gehört zu dieser Kategorie von Tools. Ein Service Layer, der auf dem Betriebssystem aufsetzt (siehe Bild 1), stellt die für parallele Ausführung erforderlichen Mechanismen zur Verfügung, und der Entwickler kann sich auf den eigentlichen Entwurf, das Verhalten der Objekte und die Kommunikation zwischen den Objekten konzentrieren. Das Tool übernimmt Routinearbeiten und die Implementierung der Basisdienste.

Bild 2: Visuelles Debuggen auf UML-Ebene. Laufzeitverhalten wie Objektverhalten und Objektkommunikation sind über animierte Sequence-Diagramme und Zustandsautomat nachvollziehbar.
Bild 2: Visuelles Debuggen auf UML-Ebene. Laufzeitverhalten wie Objektverhalten und Objektkommunikation sind über animierte Sequence-Diagramme und Zustandsautomat nachvollziehbar.
(Bild: IBM)

Das Laufzeitverhalten der Applikation kann grafisch auf UML-Ebene nachverfolgt und gesteuert werden. Hierbei handelt es sich nicht etwa um eine Simulation, sondern um den tatsächlichen, sozusagen auf UML-Ebene visualisierten Code der Applikation. Dieses „grafische Debuggen“ der Applikation ist auch auf einer Target-Plattform möglich. Alle Aspekte wie Verhalten der Zustandsautomaten, Aktivitätendiagramme, Objektinteraktion anhand von Sequenzdiagrammen, Lebenszyklus der Objekte, Variablenbelegung in Rhapsody einsehbar, während die Applikation ausgeführt wird. Der Entwickler kann das Systemverhalten auf der grafischen Modellebene validieren und dann auch testen.

Die Herangehensweise hat noch einen weiteren Vorteil: Man kann bereits zu einem frühen Zeitpunkt Prototypen zu erzeugen. Dank eines Operating System Abstraction Layers (OSAL), der das darunterliegende Betriebssystem abstrahiert, kann die Applikation per Mausklick für verschiedene Betriebssysteme übersetzt werden. Die nötigen OSAL-Adapter für die gängigsten Embedded Betriebssysteme auf dem Markt sind im Lieferumfang von Rhapsody enthalten.

Prototypenfragen frühzeitig adressieren

Bild 3: RapidPrototype-Unterstützung dank Service Layer und OSAL. Das Service Layer realisiert Basisdienste wie beispielsweise Objektkommunikation, das OSAL abstrahiert das darunterliegende Betriebssystem.
Bild 3: RapidPrototype-Unterstützung dank Service Layer und OSAL. Das Service Layer realisiert Basisdienste wie beispielsweise Objektkommunikation, das OSAL abstrahiert das darunterliegende Betriebssystem.
(Bild: IBM)

In der Multicore-Entwicklung bietet dieses Rapid-Prototyping eine elegante Möglichkeit, die Konfigurationsfragen frühzeitig zu beantworten, wie: Nutze ich SMP, AMP? Ist eine homogene oder heterogene Betriebssystemstruktur besser geeignet? Wie partitioniere ich meine Applikation hinsichtlich einer effizienten Kommunikation zwischen den Cores? Ist die Applikation performanter, wenn ich die Verteilung der Aufgaben auf die Cores dem Betriebssystem überlasse (Dynamic Load Balancing) oder definiere ich dies in der Applikation? Wie viele Cores werden benötigt?

Das frühe Prototyping versetzt die Entwickler in die Lage, das System bereits in einer möglichst frühen Entwurfsphase zu evaluieren, die richtige Konfiguration zu identifizieren und zu optimieren. Aber auch für den eigentlichen Entwicklungsprozess ist Rapid Prototyping hilfreich: So ist z.B. das Debuggen eines Systems in einer heterogenen AMP-Umgebung sehr komplex, da sich Systemanforderungen auch noch während der Entwicklung ändern können.

Applikationen gezielt für Multicore-Systeme entwickeln

Durch Multicore-Technologie kann man die Leistungsfähigkeit von Prozessoren bei unverändertem Energieverbrauch steigern oder den Energieverbrauch ohne Leistungseinbußen senken. Das lässt sich aber nur verwirklichen, wenn die Applikationen so ausgelegt sind, dass die Vorteile tatsächlich auch nutzbar gemacht werden. Dies wiederum erfordert eine völlig neue Sichtweise auf den Systementwurf: Neben den vielfältigen, neuen Konfigurationsmöglichkeiten, die Multicore bietet, müssen sich die Entwickler auch primär die Frage stellen, welche Aufgaben parallel bearbeitet werden können und wo es Synchronisationspunkte zwischen den verschiedenen Bearbeitungspfaden gibt.

Objektorientierte Entwicklung mit Hilfe von UML-Modellen und Werkzeugen wie IBM Rhapsody helfen die inhärente Parallelität der UML-Modelle in tatsächlich parallel ausführbare und plattformunabhängige Programme zu transformieren. Sie versetzen Entwickler dadurch in die Lage, Applikationen gezielt für Multicore-Systeme zu entwickeln oder zu optimieren. So lässt sich der theoretische Vorteil der Multicore-Technologie im Bereich der Embedded Systeme wirtschaftlich sinnvoll in die Realität umsetzen.

* Martin Stockl ist IT Specialist Rhapsody, IBM Watson IoT DACH.

Artikelfiles und Artikellinks

(ID:26658110)