Software-Parallelisierung für Multicore-Prozessoren, Teil 3: Performanz-Abschätzung

Von Oliver Oey * |

Anbieter zum Thema

Der häufigste Grund für den Einsatz von Mehrkernprozessoren ist die Steigerung der Leistung bzw. der Performance eines Systems. Im dritten und letzten Teil dieser Multicore-Serie geht es deshalb um richtige Performanz-Abschätzung.

Multicore-Prozessoren kommen besonders dann in Embedded-Systemen zum Einsatz, wenn der Wunsch nach einer besseren Leistung bzw. Performanz einer Anwendung besteht. Mehr Kerne versprechen in der Tat zumindest in der Theorie eine Multiplikation der Geschwindigkeit. Aber die tatsächliche Performanz hängt in der Praxis von diversen Faktoren ab.
Multicore-Prozessoren kommen besonders dann in Embedded-Systemen zum Einsatz, wenn der Wunsch nach einer besseren Leistung bzw. Performanz einer Anwendung besteht. Mehr Kerne versprechen in der Tat zumindest in der Theorie eine Multiplikation der Geschwindigkeit. Aber die tatsächliche Performanz hängt in der Praxis von diversen Faktoren ab.
(Bild: emmtrix)

Bei der Programmierung der auch im Bereich der eingebetteten Systeme immer weiter verbreiteten Mehrkernprozessoren, gibt es einige Herausforderungen, die bei rein sequentieller Programmierung nicht auftreten. Die Themen ‚Race Conditions‘ und ‚Deadlocks‘ wurden bereits in den beiden vorherigen Artikeln dieser Multicore-Serie dargestellt (zu finden auf elektronikpraxis.de sowie in den ELEKTRONIKPRAXIS-Ausgaben 4 und 6/2020). In diesem abschließenden Artikel geht es nun um die Abschätzung der Performanz.

Der häufigste Grund für den Einsatz von Mehrkernprozessoren ist die Steigerung der Performanz einer Anwendung. Durch verkürzte Berechnungszeiten sollen Ergebnisse schneller bereitgestellt oder ein höherer Datendurchsatz erreicht werden. Dabei gibt die Anzahl an Kernen zwar ein theoretisches Maximum der Beschleunigung an, in der Praxis aber hängt die Performanz von vielen Faktoren ab, die im Folgenden diskutiert werden sollen. Anschließend werden Möglichkeiten aufgezeigt, wie die parallele Performanz ermittelt werden kann.

Kostenloses Webinar zu Multicore-Programmierung

Die Komplexität der parallelen Programmierung von Multicore-Prozessoren ist nicht trivial. In einem „Best Practice Webinar zur Multicore-Programmierung“ zeigen die Experten von emmtrix die gängigsten Techniken und wie Sie Ihren Code parallelisieren, Fehler bei der parallelen Programmierung vermeiden sowie Codetransformationen richtig einsetzen, um die inhärente Parallelität Ihrer Aufgaben zu erkennen.

Termine sind am Donnerstag 30. April 2020 und am Dienstag 26. Mai 2020 jeweils um 10:00 um Uhr (MESZ). Die Dauer beträgt 75 Minuten, die Vortragssprache ist Englisch. Hier können Sie sich jetzt kostenlos registrieren: www.emmtrix.com/webinars.

Limitierungen bei der Parallelisierung

Nicht alle Teile einer Anwendung lassen sich parallelisieren. Viele Aufgaben müssen nacheinander abgearbeitet werden, wenn spätere Schritte auf Ergebnisse von vorherigen Schritten warten müssen. Dieser sequentielle Teil einer Anwendung beschränkt die mögliche Performanz-Steigerung durch weitere Kerne.

Nehmen wir als Beispiel eine Anwendung, bei der 20% der gesamten Berechnung sequentiell ausgeführt werden muss. Bei Einsatz von vier Kernen können die restlichen 80% im Idealfall vier Mal so schnell ausgeführt werden und die Ausführungsdauer auf (20% seq. + (80% /4)) = 40 % reduziert werden. Man spricht auch von einem Speedup von 2,5 (100% / 40%). Verallgemeinert ist dieses Verhalten als Amdahlsches Gesetz bekannt: S(n) = 1 / (B + 1/n(1 – B))

Dabei ist S der Speedup, n die Anzahl an parallelen Ausführungseinheiten und B der sequentielle Anteil der Anwendung. In unserem Beispiel tendiert der maximal mögliche Speedup gegen 5 (100% / 20%), perfekte Parallelisierung vorausgesetzt.

Zusätzlich entsteht durch die Aufteilung der Aufgaben auf verschiedene Recheneinheiten ein Overhead, wenn Daten zwischen den einzelnen Kernen synchronisiert oder kommuniziert werden müssen. Zeiten, in denen entweder ein Kern mit dem Kopieren von Daten beschäftigt ist oder auf neue Daten warten muss, existieren im sequentiellen Fall nicht und werden erst durch die Parallelisierung erzeugt.

Schließlich kann die Aufteilung auch das Speicherzugriffsmuster einer Anwendung verändern, was sowohl positive als auch negative Auswirkungen auf die Performanz haben kann.

Möglichkeiten zur Performanz-Abschätzung

Diese und andere Faktoren sorgen dafür, dass es schwierig ist, den zu erwartenden Zeitgewinn verlässlich abzuschätzen. Dennoch existieren verschiedene Methoden, um die Performanz der parallelen Anwendung zu ermitteln:

Profiling auf der Hardware: Hierunter versteht man das Messen von Zeiten bei der tatsächlichen Ausführung auf dem Zielsystem. Üblicherweise instrumentiert man dabei den Quellcode und markiert jeweils den Anfang und das Ende von Code-Abschnitten, für die die Zeit gemessen werden soll. Hierbei ist zu beachten, dass die Zeitmessung selbst einen Einfluss auf die Ausführungszeit hat und Messungen deshalb mehrfach an unterschiedlichen Stellen durchgeführt werden sollten, um genauere Werte zu ermitteln.

Da wirklich die Ausführung auf der Hardware gemessen wird, können alle Ausführungsdetails einschließlich Hardware-spezifischer Overheads betrachtet werden, und die erhaltenen Laufzeiten sind akkurat. Die Dauer einer Messung erfolgt in Echtzeit. Je nach Zielplattform können zudem (Debugging-) Schnittstellen und Hardware bereitgestellt sein, die eine Zeitmessung ohne Beeinflussung der tatsächlichen Ausführung ermöglichen. Die größten Nachteile dieser Methode sind zum einen, dass die Hardware verfügbar sein muss und zum anderen, dass jede Messung aufwendig an die jeweilige Zielplattform angepasst werden muss.

Simulation: Mit Hilfe einer Simulation des Zielsystems können die Zeiten der einzelnen Code-Abschnitte auch ohne Verfügbarkeit der Hardware ermittelt werden. Wichtig ist hier, dass eine Zyklen-akkurate Simulation von Prozessor, Speicher und Caches sehr zeitaufwendig ist und die Ausführung von Programmen Stunden oder Tage dauern kann. Dafür liefern sie aber auch die genauesten Werte. Werden Teile der Simulation durch einfachere Modelle ersetzt, kann die Ausführungszeit deutlich verbessert werden. Dies geschieht immer unter Verlust von Genauigkeit. Dies kann für die meisten Anwendungsfälle jedoch vernachlässigt werden.

Jetzt Newsletter abonnieren

Verpassen Sie nicht unsere besten Inhalte

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

Statische Code-Analyse: Bei einer statischen Code-Analyse wird die Performanz einer Anwendung bestimmt, ohne sie überhaupt auszuführen. Dies ermöglicht Analysen wie die Bestimmung von schlechtmöglichsten (Worstcase) Zeiten oder sehr schnelle Abschätzungen, um die wichtigsten Teile einer Anwendung zu bestimmen.

Je nach Komplexität und Aufwand können dabei Compiler-Optimierungen und Cache-Effekte mitbetrachtet werden, üblicherweise wird aber mit abstrakteren Hardware-Modellen gearbeitet, um die Ausführungszeit in Grenzen zu halten. Zudem kommt hinzu, dass nicht jeder Code ohne weiteres rein statisch analysiert werden kann, sondern noch Informationen von der Ausführung benötigt werden, um genauere Aussagen treffen zu können.

Darstellung der Auslastung der einzelnen Kerne über die Zeit und von Abhängigkeiten, die für Verzögerungen bei anderen Kernen sorgen.
Darstellung der Auslastung der einzelnen Kerne über die Zeit und von Abhängigkeiten, die für Verzögerungen bei anderen Kernen sorgen.
(Bild: emmtrix)

Zur Darstellung der parallelen Performanz werden häufig Grafiken verwendet, die ähnlich einer Gantt-Darstellung die Auslastung der einzelnen Kerne über die Zeit darstellt. In der hier gezeigten Grafik sind zusätzlich beispielhaft Abhängigkeiten dargestellt, die für Verzögerungen bei anderen Kernen sorgen.

Die automatisierte Parallelisierung

Die in dieser Artikelserie beschriebenen Herausforderungen wie Race Conditions, Deadlocks oder die Ermittlung des tatsächlichen Performanz-Gewinn haben gezeigt, dass die manuelle parallele Programmierung moderner Multicore-Prozessoren deutlich aufwendiger ist als die bisherige rein sequentielle Entwicklung. Mit steigender Komplexität der Hard- und Software ist dieser Aufwand schnell wirtschaftlich nicht mehr tragbar sowie technisch nicht mehr kontrollierbar.

Leider bleibt der Wunsch nach einer vollautomatischen Lösung aller parallelen Probleme nach wie vor unerfüllt. Dennoch gibt es Fortschritte im Bereich der Tool-Unterstützung. Automatisierte Tools wie Parallel Studio von emmtrix, können durch integrierte Performanz-Abschätzung, Synchronisation von Ressourcen, Codegenerierung und einen Correct-by-Design-Ansatz die technischen (und finanziellen) Hürden drastisch senken und ermöglichen damit die (Aus-) Nutzung moderner, performanter Hardwareplattformen.

Kostenloses Webinar zu Multicore-Prgorammierung

Die Komplexität der parallelen Programmierung von Multicore-Prozessoren ist nicht trivial. In einem „Best Practice Webinar zur Multicore-Programmierung“ zeigen die Experten von emmtrix die gängigsten Techniken und wie Sie Ihren Code parallelisieren, Fehler bei der parallelen Programmierung vermeiden sowie Codetransformationen richtig einsetzen, um die inhärente Parallelität Ihrer Aufgaben zu erkennen.

Termine sind am Donnerstag 30. April 2020 und am Dienstag 26. Mai 2020 jeweils um 10:00 um Uhr (MESZ). Die Dauer beträgt 75 Minuten, die Vortragssprache ist Englisch. Hier können Sie sich jetzt kostenlos registrieren: www.emmtrix.com/webinars.

* Oliver Oey ist Senior Engineer und Mitbegründer der emmtrix Technologies GmbH in Karlsruhe.

(ID:46492572)