Читать книгу Dojos für Entwickler 2 - Stefan Lieser - Страница 43
Aufgabe 3 Bilddateien parallel verarbeiten Alle anpacken!
ОглавлениеSie sollen aus vielen JPEG-Dateien die Stichworte extrahieren. Eine ideale Aufgabenstellung für Parallelverarbeitung. Aber läuft das Programm damit auch wirklich schneller?
Versuch macht klug. Daher soll es in der Aufgabe für diesen Monat darum gehen herauszufinden, ob die Parallelverarbeitung von Dateien das Programm beschleunigen kann. Natürlich soll dabei Flow-Design zum Einsatz kommen. Denn Flow-Design hat im Bereich der Parallelisierung einen entscheidenden Vorteil : Ein Entwurf, der zunächst ohne den Aspekt der Parallelisierung erstellt wurde, kann leicht um Parallelverarbeitung ergänzt werden. Das gilt natürlich nur, wenn überhaupt einzelne Schritte im Flow parallel ausführbar sind, ohne dass dadurch die Semantik verändert wird. Bei der Parallelisierung von Flows lassen sich zwei Fälle unterscheiden:
Es existieren im Flow bereits parallele Datenflüsse, die allerdings bislang sequenziell ausgeführt werden.
Es werden Aufzählungen von Daten verarbeitet, sodass sich eventuell mehrere Instanzen parallel um die Verarbeitung kümmern können.
Abbildung 1 zeigt den ersten Fall vor und nach der Parallelisierung.
Damit die beiden Pfade auf jeweils eigenen Threads parallel ausgeführt werden, muss jeweils zu Beginn und Ende des Pfades eine zusätzliche Funktionseinheit für den Threadwechsel sorgen. Die Funktionseinheit Asynchronize sorgt dafür, dass auf einem neuen Thread weitergearbeitet wird. Am Ende des Teil-Flows sorgt Synchronize dafür, dass der Flow auf den ursprünglichen Thread zurückkehrt. Dies ist vor allem in Verbindung mit Windows Forms und WPF wichtig, weil ein Zugriff auf die Controls meist nur aus dem UI-Thread heraus gestattet ist. Ihre erste Aufgabe für diesen Monat besteht darin, die beiden Funktionseinheiten Asynchronize und Synchronize zu implementieren. Das ist mithilfe der Klassen Thread und SynchronizationContext eine überschaubare Herausforderung.
[Abb. 1]
Parallele Pfade.
In Abbildung 2 sehen Sie den zweiten Fall für eine mögliche Parallelisierung.
Die Funktionseinheit A erhält mehrere Elemente vom Typ X und verarbeitet diese zu mehreren Elementen vom Typ Y. Der Stern zeigt an, dass statt eines einzelnen Datums eine Aufzählung von Daten fließt. Ziel ist es, die Bearbeitung der Aufzählung von mehreren parallel arbeitenden Instanzen der Funktionseinheit A ausführen zu lassen. Dazu verteilt der Scatter-Baustein die anstehenden Daten auf mehrere parallel arbeitende Funktionseinheiten. Die Ergebnisse sammelt Gather am Ende wieder ein und fasst sie zu einer Aufzählung zusammen. Um die Aufgabe nicht zu kompliziert zu machen, genügt es, Scatter und Gather mit einer fixen Anzahl von Ein- bzw. Ausgängen zu versehen. Beginnen Sie ruhig mit nur zwei Ein- bzw. Ausgängen.
Natürlich müssen die Daten sich für eine Parallelverarbeitung eignen. Müssen die Daten etwa in einer vorgegebenen Reihenfolge bearbeitet werden, wird eine Parallelisierung schwierig. Durch die parallel laufenden Threads ist nämlich die Einhaltung der Reihenfolge nicht mehr automatisch sichergestellt. Müssen die Threads zur Einhaltung der Reihenfolge aufeinander warten, bringt die Parallelisierung aus Performancesicht ohnehin nichts. Und auch bei Daten, deren Bearbeitungsreihenfolge keine Rolle spielt, müssen Sie darauf achten, dass die Daten jeweils genau einmal bearbeitet werden. [ml]
[Abb. 2]
Aufzählungen parallelisiert bearbeiten.