Parallel Studio: Das sagen die Betatester
Parallel Studio ist jetzt etwas mehr als eine Woche alt. Das schreit förmlich nach ein paar interessanten Infos rund um die Entwicklersuite. So zeigt beispielsweise ein interne Umfrage unter Betatestern:
- 75 Prozent aller teilnehmenden Entwickler konnten bereits nach 15 Minuten sinnvolle und nachvollziehbare Ergebnisse produzieren.
- Ebenfalls 75 Prozent haben Parallel Studio als “empfehlenswert” eingestuft (8 von 10 Sternen im Mittel).
- 86 Prozent der teilnehmenden Betatester glauben, dass die Threading-Methoden von Parallel Studio (OpenMP, Intel TBB, etc.) für ihre Zwecke völlig ausreichend sind.
- 71 Prozent der Betatest-Entwickler konnten einen Geschwindigkeitszuwachs bei ihren Anwendungen messen, und das nur wegen des Umstiegs auf den integrierten Intel-C++-Compiler, der natürlich äußerst multithreading-tauglich ist.
Und es gibt sogar schon erste Referenzgeschichten, die den Einsatz von Parallel Studio in ein bestehendes Projekt verdeutlichen sollen. Dazu gehört beispielsweise die in Paris ansässige Firma Open Cascade, die die gleichnamige Opensource-Software entwickelt hat und für Kunden in deren Anwendungen integriert. Mit Open Cascade lassen sich komplexe und sehr aufwendige 3D-Modelle erstellen, wie sie beim Produktdesign, in der Simulationstechnik und in anderen Bereichen verwendet werden.
Da die Berechnung und grafische Umsetzung solcher 3D-Modelle sehr rechenintensiv und Open Cascade zudem C++-basiert ist, kam für mehr Leistung und schnellere Berechnungen Parallel Studio zum Einsatz. Schnell zeigte sich, dass der Parallel Amplifier typische Hotspots mit wenig Aufwand entdecken konnte. So ließ sich beispielsweise die Berechnung von geometrischen Flächen drastisch beschleunigen, indem dem betreffenden Algorithmus ein eigener Thread zugewiesen werden konnte, der bei Bedarf immer wieder parallel ausgeführt werden kann.
Aber auch der Parallel Inspector half dabei, Open Cascade zu verbessern und schneller zu machen. Das führte insgesamt zu einer doppelt so schnellen Rechengeschwindigkeit und einer Reduzierung von Speicherproblemen (Meomory Leaks).
OpenMP: Schleifen anpassen für Multithreading-Ausführung
Gestern habe ich mit einer neuen Serie angefangen, die sich intensiv mit dem Thema OpenMP beschäftigt. Im ersten Teil ging es sehr fundamental um die Voraussetzungen, die eine Schleife erfüllen muss, um per OpenMP multithreading-tauglich zu sein. Heute geht es um die Frage, welche Dinge zu beachten sind, damit eine Schleife ordnungsgemäß in mehrere Threads aufgeteilt werden kann.
Zunächst einmal: Das Threaden von Schleifenkonstrukten bedeutet nichts anderes, als dass unabhängige Schleifeniterationen auf mehreren Threads gleichzeitig ausgeführt werden können, was natürlich Rechenzeit pro Takt spart. Hierzu wird die Schleife in eine neue Form gebracht, die das Parallelisieren derselben überhaupt erst ermöglicht. Dies ist aber nur umsetzbar, wenn die Schleife keine Abhängigkeiten aufweist.
Daher muss man als Entwickler zunächst einmal mit einem passenden Tool wie VTune Performance Analyzer diejenige Schleife finden, die insgesamt die meiste Rechenzeit verschlingt. Anschließend wird diese umstrukturiert, um festzustellen, dass keine iterationsübergreifenden Abhängigkeiten bestehen. Erst dann sollte diese Schleife mithilfe eines OpenMP-Pragmas parallelisiert werden.
OpenMP: fünf Bedingungen für parallele Schleifen
Das Thema OpenMP steht bei vielen Lesern dieses Blogs hoch im Kurs. Das liegt zum einen an der Parallel-Computing-Seite von MSDN, auf der ein entsprechender Beitrag lange verlinkt war. Zum anderen findet Google meine OpenMP-Bemühungen wohl ganz nett, zumindest steht besagter Artikel im deutschsprachigen Index auf dem fünften Platz.
Daher starten wir heute mit einer Serie, die sich mit kleineren und größeren Aspekten der OpenMP-basierten Programmierung beschäftigt. Also mit solchen Fragen wie:
- Welche Bedingungen müssen erfüllt sein, damit OpenMP-basierende Schleifen überhaupt in parallelen Threads ausgeführt werden können?
- Welche Dinge sind zu beachten, damit eine Schleife ordnungsgemäß in mehrere Threads aufgeteilt werden kann?
- Wie lässt sich möglicher Threading-Overhead vermeiden?
- Wie kann man das Optimum aus OpenMP herausholen?
- Wie lassen sich sinnvoll OpenMP-Bibliotheksfunktionen und -Umgebungsvariablen einsetzen?
- Wie geschieht das Kompilieren und Debuggen mithilfe von OpenMP?
- Wovon hängt eine maximale Multithread-Leistung auf OpenMP-Basis ab?
Welche Bedingungen müssen erfüllt sein, damit OpenMP-basierende Schleifen überhaupt in parallelen Threads ausgeführt werden können?
1. In der Version 2.5 müssen Schleifenvariablen vom Typ vorzeichenbehafteter Integer sein. Mit der OpenMP-Spezifikation 3.0 ist diese Beschränkung weggefallen.
2. Die Vergleichsoperation muss in der Form loop_variable <, <= oder >= loop_invariant_integer sein.
3. Der Inkrementteil (z.B. i++) der for-Schleife muss additiv oder substraktiv sein, und zwar mit einem schleifeninvarianten Wert.
4. Ist die Vergleichsoperation vom Typ < oder <=, muss die die Schleifenvariable bei jeder Iteration erhöht werden. Umgekehrt muss die Variable dekrementiert werden (also bei > oder >=).
5. Die Schleife muss zwingend einen Eintritt und einen Austritt haben. Daher sind nicht erlaubt: Sprünge aus der Schleife heraus bzw. von außen in die Schleife hinein. Das gilt beispielsweise für goto- oder break-Anweisungen oder für Ausnahmebehandlungen. Eine Ausnahme dieser Regel stellt die exit-Anweisung dar, die die komplette Anwendung beendet.
Diese Bedingungen müssen aus Kompilierungsgründen eingehalten werden. Andernfalls kann keine automatische Parallelisierung erfolgen.
Workshop: parallel Programmieren mit OpenMP
Über OpenMP habe ich hier schon des öfteren gebloggt, aber noch nie so wirklich im Detail. Das wird sich heute schlagartig ändern, denn ein lieber Kollege (danke, Edmund!) hat mir am Wochenende einen sehr anschaulichen Artikel zukommen lassen, der mir als Grundlage für das heutige Posting dient. Den kompletten Beitrag samt Programmierbeispiel anhand der Kreiszahl Pi gibt es als PDF zum Download.
Zunächst einmal: OpenMP liegt in der Version 3.0 vor und stellt eine standardisierte Programmierungsmethode dar. In Sachen Komplexität bewegt sie sich zwischen den herkömmlichen Threads – also API-Threads, PThreads oder WinThreads – und den höher entwickelten Intel TBB oder der geplanten Parallel Pattern Library (PPL), die von Microsoft kommen wird.
Daraus ergeben sich zwei wesentliche Aspekte: OpenMP ist weitaus einfacher zu verstehen, zu implementieren und zu testen als die Low-Level-Threads, bei denen sich der Programmierer um viele Dinge selbst kümmern muss, was das Ganze natürlich extrem fehleranfällig macht.
Die Kehrseite von OpenMP ergibt sich aus der geringeren Komplexität: Nicht alle Programmieraufgaben lassen sich mit OpenMP erledigen, was den Entwickler natürlich ein wenig einschränkt. OpenMP versteht sich vor allem sehr gut auf das Parallelisieren von rechenintensiven Schleifenkonstrukten.
Parallel-Bibliotheken helfen bei der Software-Entwicklung
Ende Januar habe ich auf Basis eines Vortrags von Walter Tichy, Uniprofessor in Karlsruhe, 12 Thesen und 12 passende Antithesen zum Thema Multicore-Programmierung aufgestellt. These Nummer 12 beschäftigt sich mit Professor Tichys Aussage, es gäbe für bestimmte, immer wiederkehrende Aufgaben der Parallelprogrammierung noch nicht die passenden Tools auf dem Markt.
Schon seinerzeit habe ich dagegen gesprochen, da sehr wohl Software-Werkzeuge existieren wie die Integrated Performance Primitives (IPP), die vor allem Entwickler von Multimedia-Software bei ihrer Arbeit unterstützen sollen. So basieren zahlreiche MP3- und AAC-Encoder/-Decoder auf Teilen der IPP-Bibliotheken, in denen übrigens viele Mannjahre Entwicklungsarbeit stecken.
Mit den IPP lassen sich einzelne Funktionen für das Encoden von Audio- und Videostreams mehr oder weniger per Drag & Drop für eigene Anwendungen nutzen, die dann bestimmte Aufgaben hochparallelisiert ausführen – ohne dass der Programmierer sich darüber Gedanken machen muss, wie dies funktioniert. Bekannte Beispiele hierfür sind H.264-, MPEG-4- und AAC-basierte Encoder.
Aber auch im medizinischen Bereich für die rechenintensive Auswertung von Ultraschallbildern kommen IPP-Bibliotheken zum Einsatz. Damit lassen sich hochkomplexe 3D-Bilder deutlich schneller analysieren, da die vorhandenen Prozessoren simultan die Berechnungen durchführen können. Somit spart der Einsatz der IPP im günstigsten Fall drei bis vier Mannjahre Entwicklungszeit, die das Programmieren solcher Parallel-Bibliotheken resp. der zugehörigen Anwendung in Anspruch nähmen.
Serie: Mit Parallel Studio Anwendungen multithreaden (2)
Am Freitag habe ich eine kleine Serie um Parallel Studio gestartet. Im ersten Teil geht es um den Parallel Composer, mit dessen Hilfe paralleler Quellcode erzeugt werden kann. Das heutige zweite Kapitel handelt von den Komponenten Parallel Inspector und Parallel Amplifier.
Mit dem Parallel Inspector lassen sich Multithread-Anwendungen in vielfältiger Weise debuggen. Es geht allerdings um weit mehr als das bloße Aufspüren von Quellcode-Fehlern:
- Es spielt keine Rolle, welche Programmiermethode eingesetzt wird. Parallel Inspector unterstützt nämlich OpenMP (besser: er basiert darauf), kommt aber auch mit Intel TBB und Windows Threads klar.
- Fehler wie Dead Locks und Race Conditions werden zur Laufzeit gefunden, bevor sie der Kunde findet.
- Das Laufzeitverhalten wird vollständig aufgezeichnet, um so nachträglich und detailliert mögliche Fehler und Probleme innerhalb der parallelisierten Anwendung zu identifizieren.
- Im Gegensatz zu anderen Testtools können schwer auffindbare, nicht-deterministische Fehler mit Parallel Inspector aufgespürt werden.
- Pate des Parallel-Debuggers ist der Thread Checker. Damit bekommt man ein zuverlässiges, weil erprobtes Tool an die Hand zum Debuggen seiner Anwendungen.
- Parallel Inspector fügt sich nahtlos in Visual Studio ein.
Serie: Mit Parallel Studio Anwendungen multithreaden (1)
Heute beginnt auf dem Software Dev Blog die Serie “Mit Parallel Studio Anwendungen multithreaden”. In den geplanten Folgen geht es im Einzelnen um die Komponenten Parallel Composer, Parallel Inspector und Parallel Amplifier.
Der erste Teil handelt vom Parallel Composer, der mit einer Reihe nützlicher Tools die Parallelisierung serieller Anwendungen erleichtern soll. Hierfür bietet er
- vereinfachte Multithread-Funktionen, die allesamt auf OpenMP 3.0 basieren und als solche im Hintergrund eingesetzt werden
- Vektorisierungspragmas in Kombination mit den SSE2-/SSE3-/SSSE3- und SSE4-Befehlen
- einfache Integration in die Entwicklungsumgebung von Microsoft Visual Studio
- Intel Parallel Debugger Extensions als Plugin für Visual Studio
- Lambda-Funktionen (nur C++) für den vereinfachten Austausch mit Intel TBB
- Unterstützung der Vektorschreibweise (arr[i])
- automatische Parallelisierung von Quellcode
- Diagnosetools, die beim Entwickeln von Multithread-Quellcode helfen
- zahlreiche Multithread-Beispiele mit dem entsprechenden Quellcode
Und am Montag gibt es dann mehr Infos zu Parallel Inspector und Parallel Amplifier ein anschauliches Beispiel, Infos zu OpenMP 3.0 und einiges mehr. Und die zusätzlichen Infos zu OpenMP und Co. gibt es am Dienstag …
Multithreading-Konzepte: OpenMP, APIs und Intel TBB
Für die parallele Programmierung bieten sich diverse Alternativen an, von denen hier drei vorgestellt werden sollen: OpenMP, Threading-APIs und Intel Threading Building Blocks.
OpenMP: Diese Threading-Methode ist relativ simpel zu handhaben, da in den Quellcode sogenannte Pragmas eingebaut werden, die der jeweilige Compiler richtig interpretieren kann – oder auch nicht. OpenMP eignet sich vor allem für die Parallelisierung einfacher Schleifenkonstrukte und prozeduraler Datenstrukturen. Aufgrund seiner Historie lässt sich OpenMP gut in nativen Programmierumgebungen (C++ und Fortran) einsetzen, dafür leider gar nicht in managed Code (C#, .NET).
Threading-APIs: Spezielle Threading-APIs wie Win32- oder POSIX eignen sich nicht so gut zum Implementieren von Parallel-Code. Dabei werden die Multithreading-Konstrukte in eigenen Funktionen verpackt. Die Ergebnisse werden dann als Pointer übergeben, und hier steckt die Schwierigkeit bei der Arbeit mit Threading-APIs: Funktionsprototypen und Datenstrukturen müssen aufwendig modifiziert werden, was häufig die Abstraktion des Codes und das Programmdesign zerstört. Außerdem muss man sich als Programmierer selbst um das Erzeugen, Verwalten und Synchronisieren der Threads kümmern, was sehr mühsam ist. Daneben unterstützen Threading-APIs C++ nur sehr schlecht und oft gar nicht.
Intel Threading Building Blocks: Hierbei handelt es sich um eine C++-Bibliothek, die ähnlich wie die Standard Template Library eines herkömmlichen Compilers aufgebaut ist. Die Intel TBB stellen hochentwickelte Abstraktionsmodelle zur Verfügung, um eine flexible Programmierung zu ermöglichen. Das bedeutet, dass beispielsweise Iteratoren, die in Container verpackt sind, mithilfe der Intel TBB relativ einfach parallelisiert werden können.
Die Idee hierbei ist recht simpel: Anstatt Threads spezifiziert man einzelne Aufgaben (Tasks), die der TBB Scheduler auf die vorhandenen Hardware-Threads abbildet. Man muss sich also nicht mehr um die Synchronisation der Threads und ähnliches kümmern. Außerdem skaliert eine mithilfe der Intel TBB parallelisierte Anwendung sehr gut, da je nach verfügbaren Prozessorkernen und damit verbundenen Threads die Software um ein Vielfaches schneller ausgeführt werden kann.
Tipps, Infos & Tricks rund ums parallele Programmieren
Das Thema „Paralleles Programmieren“ ist ein weites Feld, auf dem man sich ohne die passenden Tipps und Tricks, ohne hilfreiche Anleitungen und nützliche Webseiten-Empfehlungen ziemlich schnell verirren kann. Aus diesem Grund hat das Medienunternehmen Jupiter Online Media gemeinsam mit seinem Partner Intel eine Webseite ins Leben gerufen, die genau das leisten soll: helfen, anleiten, empfehlen.
Diese Seite nennt sich go-parallel.com und berichtet in regelmäßigen Abständen über das parallele Multicore-Universum der Software-Entwicklung. Zu diesem Zweck ist die Seite in fünf Bereich unterteilt: „Getting Started“, „Concurrent Programming“, „Community and Opinion“, „Tools and Tips“ und „Advanced Concepts“.
So findet man in „Getting Started“ hilfreiche Anleitungen, wie man beispielsweise eine komplette TBB-Umgebung unter Windows einrichtet und wie die Programmierung einer TBB-kompatiblen Anwendung funktioniert. Aber auch Themen wie OpenMP werden dort behandelt.
