• Keine Ergebnisse gefunden

Paralleles Rechnen Konzepte und Anwendungen im Data Mining

N/A
N/A
Protected

Academic year: 2022

Aktie "Paralleles Rechnen Konzepte und Anwendungen im Data Mining"

Copied!
96
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Paralleles Rechnen

Konzepte und Anwendungen im Data Mining

Stefan Wissuwa 1. Dezember 2008

Thesis zur Erreichung des Grades

Master of Science (M.Sc.) in Wirtschaftsinformatik

Hochschule Wismar - Fakultät für Wirtschaftswissenschaften

Eingereicht von: Stefan Wissuwa, Dipl. Wirt.-Inf. (FH) Erstbetreuer: Jürgen Cleve, Prof. Dr. rer. nat.

Zweitbetreuer: Uwe Lämmel, Prof. Dr.-Ing.

(2)

Inhaltsverzeichnis

1 Einleitung 1

1.1 Motivation . . . 1

1.2 Anwendungsgebiete . . . 2

1.3 Inhalt der Arbeit . . . 3

1.4 Begriffsklärung . . . 4

I Grundlagen der parallelen Datenverarbeitung 5

2 Stufen der Parallelisierung 6 3 Parallele Architekturen 7 3.1 Flynnsche Klassifizierung . . . 7

3.2 Speichermodelle . . . 7

3.2.1 Rechner mit gemeinsamem Speicher . . . 8

3.2.2 Rechner mit verteiltem Speicher . . . 9

3.3 Prozesse / Threads . . . 10

3.4 Client-Server-Architekturen . . . 10

3.5 Cluster-Computing . . . 11

3.6 Grid-Computing . . . 11

4 Parallelisierungsebenen 13 4.1 Parallelität auf Instruktionsebene . . . 13

4.2 Parallelität auf Datenebene . . . 13

4.3 Parallelität in Schleifen . . . 14

4.4 Parallelität auf Funktionsebene . . . 14

5 Parallele Programmiermodelle 16 5.1 Darstellung . . . 16

5.2 Strukturierung . . . 17

5.3 Datenverteilung und Kommunikation . . . 17

5.3.1 Broadcast . . . 17

5.3.2 Scatter . . . 18

5.3.3 Gather . . . 18

5.3.4 Reduktion . . . 19

5.4 Synchronisation . . . 19

5.4.1 Kritische Abschnitte . . . 20

5.4.2 Barrieren . . . 20

5.4.3 Locks . . . 20

6 Einflussfaktoren Paralleler Programme 21 6.1 Parallele Skalierbarkeit . . . 21

6.1.1 Speedup . . . 21

6.1.2 Amdahl’sches Gesetz . . . 21

6.1.3 Gustafson-Gesetz . . . 22

6.1.4 Karp-Flatt-Metrik . . . 24

(3)

6.2 Load Balancing und Scheduling . . . 25

6.3 Lokalität . . . 25

6.4 Speichersynchronisation . . . 26

II Bibliotheken und Systeme 28

7 Unified Parallel C 29 7.1 Verfügbarkeit . . . 29

7.2 Parallelisierungskonzept . . . 29

7.3 Speichermodell . . . 30

7.4 Synchonisation . . . 32

7.5 Globale Operatoren . . . 32

8 Message Passing Interface 33 8.1 Verfügbarkeit . . . 34

8.2 Parallelisierungskonzept . . . 34

8.3 Speichermodell . . . 34

8.4 Synchronisation . . . 34

8.5 Globale Operatoren . . . 34

9 OpenMP 35 9.1 Verfügbarkeit . . . 35

9.2 Parallelisierungskonzept . . . 35

9.3 Speichermodell . . . 35

9.4 Synchronisation . . . 36

9.5 Globale Operatoren . . . 37

10 Andere 38 10.1 BOINC . . . 38

10.2 BLAS . . . 38

10.3 PThreads . . . 38

10.4 Parallel Virtual Machine . . . 38

11 Vergleichende Betrachtung 40 11.1 Implementierung . . . 40

11.1.1 Matrizenmultiplikation Seriell . . . 40

11.1.2 Matrizenmultiplikation UPC . . . 40

11.1.3 Matrizenmultiplikation MPI . . . 42

11.1.4 Matrizenmultiplikation OpenMP . . . 42

11.2 Performance . . . 43

11.3 Bewertung . . . 45

11.3.1 UPC . . . 45

11.3.2 MPI . . . 46

11.3.3 OpenMP . . . 48

III Parallelisierung im Data Mining 49

(4)

12 Data Mining Grundlagen 50

12.1 Ablaufmodell . . . 50

12.2 Klassifikation der Verfahren . . . 51

12.3 Künstliche Neuronale Netze . . . 53

12.3.1 Feed-Forward-Netze . . . 53

12.3.2 Selbstorganisierende Karten . . . 54

13 Parallele Algorithmen 56 13.1 Serielle Selbstorganisierende Karte . . . 56

13.2 Parallele Selbstorganisierende Karte . . . 57

13.3 Performance Test . . . 59

14 Parallele Modelle 61 14.1 Hierarchische Kohonen-Karten . . . 61

14.1.1 Konzept . . . 61

14.1.2 Umsetzung . . . 64

14.1.3 Testaufbau . . . 67

14.1.4 Vergleich der Modellqualität . . . 70

14.1.5 Vergleich der Rechengeschwindigkeit . . . 72

14.2 Feed-Forward-Netze . . . 73

14.2.1 Konzept . . . 73

14.2.2 Umsetzung . . . 73

14.2.3 Vergleich der Modellqualität . . . 74

14.2.4 Vergleich der Rechengeschwindigkeit . . . 75

IV Zusammenfassung und Ausblick 76 V Ehrenwörtliche Erklärung 79 VI Anhang 80

A Schnittstellen und Bibliotheken 81 A.1 UPC Konsortium . . . 81

A.2 Compilerübersicht . . . 82

B Messwerte 84 B.1 Messwerte Matrizenmultiplikation . . . 84

B.2 Messwerte SOM . . . 86

B.3 Messwerte Feed-Forward-Netz . . . 88

B.4 Inhalt der CD . . . 89

(5)

Algorithmenverzeichnis

1 Matrizenmultiplikation Seriell . . . 41

2 Matrizenmultiplikation MPI Global . . . 43

3 SOM Seriell . . . 57

4 Parallele SOM mit OpenMP . . . 59

5 Hierarchische SOM . . . 68

(6)

Abbildungsverzeichnis

1 Gemeinsames Speichermodell UMA . . . 8

2 Gemeinsames Speichermodell NUMA . . . 8

3 Verbindungsnetzwerke . . . 9

4 Effiziente Broadcast-Operation . . . 18

5 Effiziente Akkumulations-Operation . . . 19

6 Parallele Skalierbarkeit nach Amdahl . . . 22

7 Parallele Skalierbarkeit nach Amdahl . . . 23

8 Speedup Amdahl vs. Gustafson . . . 24

9 Row- vs. Column-first Ordering . . . 26

10 Message-Passing . . . 33

11 OpenMP Fork-Join-Modell . . . 36

12 Performance UPC . . . 44

13 Performance OpenMP . . . 45

14 Performance MPI . . . 45

15 Performance MPI vs. MPI Global . . . 46

16 Performance OpenMP vs. MPI Global . . . 47

17 Performance OpenMP vs. MPI Global . . . 47

18 CRISP-DM Phasenmodell . . . 51

19 Rechenzeit SOM OpenMP für kleine Karten . . . 60

20 SOM OpenMP Rechenzeiten und Speedup nach Kartengröße . . . 60

21 U-Matrix einer Kohonen-Karte . . . 62

22 Aufteilung einer SOM . . . 63

23 Interpolation der Gewichte . . . 63

24 Clusterqualität vs. Lernrate / Kartengröße . . . 69

25 U-Matrix Seriell . . . 71

26 U-Matrix Hierarchisch . . . 71

27 Clusterqualität . . . 71

28 Speedup SOM Parallel / Seriell . . . 72

(7)

Tabellenverzeichnis

1 Linpack Top-5 Supercomputer Stand 06/2008 . . . 12

2 Übersicht UPC-Compiler . . . 82

3 OpenMP-fähige Compiler . . . 83

4 Matrizenmultiplikation Seriell . . . 84

5 Matrizenmultiplikation UPC . . . 84

6 Matrizenmultiplikation OpenMP . . . 85

7 Matrizenmultiplikation MPI Master-Worker . . . 85

8 Matrizenmultiplikation MPI Global . . . 86

9 Clusterqualität (seriell) in Abhängigkeit von Lernrate und Kartengröße . . . 86

10 Clusterqualität (parallel) in Abhängigkeit von Lernrate und Kartengröße . . . . 87

11 Rechenzeit in Abhängigkeit von Kartengröße und Parallelisierungsgrad . . . . 87

12 Berechnungszeiten Parallele SOM mit OpenMP . . . 88

13 Erkennungsrate Teilklassifikatoren . . . 88

14 Rechenzeiten und Erkennungsrate n-Fach vs. binär nach Netzgröße . . . 89

(8)

1 Einleitung

1.1 Motivation

Parallelrechner, Mehrkernprozessoren, Grid-Computing und seit geraumer Zeit Cloud-Com- puting sind Schlagworte, die immer dann genannt werden, wenn es um enorme Rechenleistung von Computern geht. Doch um was handelt es sich dabei genau?

Die Entwicklung schnellerer Prozessoren erfolgte bisher zu einem signifikanten Anteil durch immer stärkere Miniaturisierung der Schaltkreise, was eine höhere Zahl an Transistoren pro Chip und höhere Taktraten erlaubte. Die Anzahl der Transistoren verdoppelt sich etwa alle 18 Monate. Dieser Zusammenhang wurde 1965 empirisch durch Gordon Moore festgestellt und wird daher auch als Moore’sches Gesetz bezeichnet1. Obwohl der dafür notwendige technolo- gische Aufwand mit der Zeit immer größer wurde, wird diese Steigerungsrate auch in näch- ster Zukunft beibehalten werden können, bis die physikalische Grenze erreicht ist. Eine stetige Steigerung der Taktraten stellt sich bereits als sehr viel schwieriger heraus, da die damit ver- bundene Abwärme des Prozessors nur sehr schwer zu handhaben ist und bereits Werte erreicht hat, die - relativ zur Oberfläche - etwa der Heizleistung einer Herdplatte gleichkommen. Statt die Geschwindigkeit nur durch höhere Taktraten zu steigern, wurde die Komplexität der Pro- zessoren so weit erhöht, dass bereits mehrere Prozessorkerne auf einem Chip zusammengefasst werden und somit das, was man unter einem Prozessor-Chip versteht, selbst einen kleinen Par- allelrechner bildet.2 Doch auch eine stetige Erhöhung der Anzahl der Prozessorkerne ist nicht unbedingt sinnvoll. Da Prozessoren heute um ein Vielfaches schneller Arbeiten als Daten vom Hauptspeicher zum Prozessor übertragen werden können, sind schnelle, teure und damit kleine Zwischenspeicher - Caches - notwendig. Da jeder Prozessorkern einen eigenen Cache besitzt, aber für alle Prozessorkerne ein konsistenter Speicherinhalt sichergestellt sein muss, sind Syn- chronisationsmechanismen notwendig, deren Komplexität mit der Zahl der Prozessoren steigt.

Da eine Synchronisation zudem Zeit kosten, schmälert dies den Geschwindigkeitsgewinn durch zusätzliche Prozessorkerne. In bestimmten Fällen können zusätzliche Prozessoren sogar dazu führen, dass ein Programm langsamer wird3. Diese vielfältigen Abhängigkeiten, die so auch in größerem Maßstab für Rechennetze gelten, führen dazu, dass Parallelisierung auf technischer wie auch auf softwaretechnischer Seite keine triviale Aufgabe ist.

Parallelrechner waren bis vor wenigen Jahren hauptsächlich in der wissenschaftlichen Simula- tion im Einsatz. Sie erlaubten es erstmals, komplexe Phänomene, deren physische Analyse zu aufwändig, teuer oder gefährlich ist, am Computer zu simulieren. Rund um diese Simulations- technik hat sich ein eigener Wissenschaftszweig etabliert, der unter dem Begriff Computational Science bekannt ist.

Beginnend mit der Einführung der ersten Pentium Dual-Core Prozessoren für den Consumer- Markt durch die Firma Intel Corp., sind heute kaum noch aktuelle PCs auf dem Markt zu finden, die nicht mindestens einen Doppelkern-Prozessor enthalten. Obwohl die jeweiligen Ziele, für die diese Technologien entwickelt werden, höchst unterschiedlich sind, gleichen sie sich jedoch in einem Punkt: die Steigerung der Leistungsfähigkeit von Computersystemen erfolgt nicht hauptsächlich durch höhere Taktrate, sondern durch Parallelisierung. Dies wird dazu führen,

1Vgl.: [RAUBER2007] S.100

2Vgl.: [RAUBER2008] S.6ff.

3Vgl.: Linux-Magazin, Ausgabe 11/2008, MySQL

(9)

dass verstärkt parallele Programmiertechniken in der Softwareentwicklung eingesetzt werden müssen, um die Leistung auch nutzen zu können.

Doch auch durch Parallelisierung können nicht unbegrenzt nutzbar höhere Rechengeschwin- digkeiten erzielt werden. Die Leistungsangaben für Supercomputer mögen einen in Erstaunen versetzen, jedoch ist dabei zu beachten, dass diese Leistung nur für sehr spezielle Program- me auch wirklich genutzt werden kann - nämlich für Programme oder Algorithmen, die sich überhaupt parallelisieren lassen. Die 1,026 Peta-Flop/s des derzeit weltweit schnellsten Super- computers4 werden nur durch Kombination von über hunderttausend Mehrkern-Prozessoren erreicht. Diese Leistung zur Lösung einer Aufgabe bündeln zu wollen bedeutet, die Aufgabe in über hunderttausend separate Teilaufgaben zu zerlegen, was weder immer möglich noch stets sinnvoll ist5.

Eine Bürosoftware wird auf einem Parallelrechner nicht unbedingt schneller ausgeführt wer- den, da sie meist nur einen einzigen der vorhandenen Prozessoren nutzen kann. Eine komplexe physikalische Simulation hingegen kann enorm von der Verteilung auf mehrere Prozessoren profitieren, sofern der Algorithmus diese Aufteilung zulässt. Data-Mining ist ein weiteres An- wendungsgebiet, für das Parallelisierung vorteilhaft sein kann, da sehr große Datenmengen zu verarbeiten sind und dafür komplexe Algorithmen eingesetzt werden.

Die langen Rechenzeiten, die für das Erstellen eines Data-Mining-Modells notwendig sind, behindern eine interaktive und intuitive Arbeitsweise bei der Exploration von Datenmengen.

Um Zeit zu sparen, können mehrere unterschiedliche Modelle nach dem Versuch-und-Irrtum- Prinzip parallel berechnet werden. Dies erfordert jedoch große Planungssorgfalt und führt in der Regel zu vielen überflüssigen Berechnungen und damit zur Vergeudung von Rechenzeit.

Ein Ansatz ist, die Gesamtrechenzeit eines Experiments zu verringern, in dem sowohl der Data- Mining-Prozess als auch einzelne Algorithmen parallel ausgeführt werden. Vor dem Hinter- grund, dass selbst aktuelle, kostengünstige PCs häufig Mehrkern-Prozessoren enthalten, ist eine Parallelisierung umso interessanter.

1.2 Anwendungsgebiete

Für parallele Rechnerarchitekturen lassen sich prinzipiell zwei Anwendungsgebiete unterschei- den:6

DasHigh-Availability-Computing dient der Zurverfügungstellung ausfallsicherer Dienste, bei- spielsweise für Datenbanken oder Web-Server, indem alle anfallenden Aufgaben nach Bedarf auf einzelne Knoten verteilt werden und dadurch auch der Ausfall einzelner Knoten kompen- siert werden kann.

DasHigh-Performance-Computingdient vor allem der Bündelung von Rechenleistung, um ei- ne einzelne Aufgabe entweder schneller oder sehr viel genauer zu lösen7. Dies ist auch das Anwendungsgebiet paralleler Algorithmen und Inhalt dieser Arbeit.

Es existieren eine Reihe von wissenschaftlichen Anwendungen, die in großem Maßstab auf Parallelisierung setzen und die durch die Art, diese zu realisieren, in der Öffentlichkeit große

4Siehe Tabelle 1 auf Seite 12.

5Siehe Kapitel 6 auf Seite 21.

6Vgl.:[BAUKE2006] S. 31ff.

7Zur Unterscheidung siehe Kapitel 6.

(10)

Popularität erlangt haben. Die wohl bekanntesten Vertreter gehören zur Gruppe der auf dem BOINC-Framework8 basierenden at-Home-Projekte, bei denen durch ans Internet angeschlos- senen PCs ein Parallelrechner nach dem Master-Worker-Prinzip aufgebaut wird. Da hierbei auch sehr viele Privat- und Bürorechner zum Einsatz kommen, werden diese Verfahren auch als Desktop-Grid-Computing bezeichnet. Die bekanntesten Projekte sind Seti@Home9 und Fol- ding@Home10.

Seti@Home dient der Analyse von Radiosignalen auf Muster, die von einer extraterrestrischen Intelligenz stammen könnten. Obwohl bisher erfolglos, ist das Projekt wohl unbestritten der populärste Vertreter seiner Art, vor allem unter Privatpersonen. Diese stellen Rechenzeit zur Verfügung, die sie selbst nicht nutzen, indem sie eine spezielle Software - in der ursprünglichen Version ein Windows-Bildschirmschoner - installieren, der Datenpakete von einem Server lädt und das Ergebnis der Berechnung zurückschickt.

Folding@Home funktioniert auf die gleiche Weise, nur ist das Ziel die Bestimmung der Ter- tiärstruktur11 von Proteinen. Da die Funktion eines Proteins nicht nur von dessen chemischer Zusammensetzung - die durch die DNA codierte Aminsosäuresequenz - abhängt, sondern auch von dessen räumlicher Struktur. Die Ausbildung der dreidimensionalen Struktur aus einer lan- gen Kette von Aminosäuren wird als Faltung bezeichnet, wobei es mehrere Varianten gibt. Nur die physiologisch korrekte Form kann die ihr zugedachte Funktion erfüllen, falsch gefaltete Proteine haben eine reduzierte, keine oder im schlimmsten Fall pathogene Funktion. Es wird vermutet, dass Krankheiten wie BSE oder die Kreutzfeldt-Jakob-Krankheit durch falsch gefal- tete Proteine (Prionen) hervorgerufen werden. Neben der Erforschung, wie und unter welchen Bedingungen der Faltungsprozess genau funktioniert, ist die Bestimmung der Tertiärstruktur ein wichtiger Schritt, wenn es gilt, die Funktion eines neu entdeckten Gens des dadurch kodierten Proteins herauszufinden.

Weitere, jedoch weniger populäre Projekte sind zum Beispiel Docking@Home12 zur Unter- suchung der Molekülbindungen zwischen Liganden und Proteinen in der Biochemie sowie NQueens@Home13 zur Lösung des N-Damen-Problems auf Feldern größer als 26x26 Einhei- ten.

1.3 Inhalt der Arbeit

Diese Arbeit befasst sich mit den Anwendung von Parallelisierungstechniken auf dem Gebiet des Data-Mining. Da das Thema dieser Arbeit viele Teilbereiche der Informatik berührt, die selbst wiederum sehr Umfangreich sind, gliedert sich diese Arbeit in drei Teile, die jedes für sich eine eigenständige thematische Einheit bilden.

Der Erste Teil stellt eine hauptsächlich konzeptionelle Einführung in die Thematik des par- allelen Rechnens dar. Es werden Begriffe und die theoretischen Grundlagen erläutert sowie grundlegende Modelle und Konzepte vorgestellt.

Der Zweite Teil widmet sich konkreten Implementationen der im ersten Teil vorgestellten Kon- zepte. Der Schwerpunkt liegt auf Sprachen, Schnittstellen und Bibliotheken für die parallele

8Siehe dazu Kapitel 10.1.

9http://setiathome.berkeley.edu/

10http://folding.stanford.edu/

11Vgl.: [KNIPPERS2001] S. 37ff.

12http://docking.cis.udel.edu/

13http://nqueens.ing.udec.cl/

(11)

Programmierung, die relativ verbreitet und frei verfügbar sind. Es werden ausgewählte Schnitt- stellen vorgestellt, deren Arbeitsweise anhand von Beispielen erläutert und eine erste verglei- chende Bewertung vorgenommen.

Der Dritte Teil behandelt das Thema Data Mining und ausgewählte Algorithmen. Es wird un- tersucht, inwiefern sich Verfahren parallelisieren lassen, welcher Aufwand hierfür notwendig ist und welche Resultate erzielt werden können. Insbesondere die Parallelisierung von Data- Mining-Modellen unter Verwendung vorhandener, rein sequentieller Data-Mining-Algorithmen wird untersucht.

1.4 Begriffsklärung

Da aufgrund der Komplexität des Themas und der Vielzahl der angeschnittenen Themen zwangs- läufig Überschneidungen von Begriffen auftreten, werden der Einfachheit halber folgende Be- griffe verwendet:

Als „Prozessor” wird in dieser Arbeit nicht der physikalische Chip, sondern die tatsächlich ausführende Recheneinheit bezeichnet. Demzufolge besitzt ein Computer mit einem Mehrkern- Prozessor-Chip eine entsprechende Anzahl an Prozessoren. Diese Sichtweise ist aus dem Grund günstig, da es sich hier hauptsächlich um die Software-Sicht der parallelen Programmierung geht, und weniger um die Hardware. Zudem stellt sich ein Mehrkern-Prozessor aus Sicht eines Programms ebenfalls als eine Anzahl von Einzelprozessoren dar14.

In der Literatur wird zwischen Prozessen und Threads unterschieden, in dieser Arbeit wird nur der Begriff Prozesse verwendet. Der Grund dafür ist, dass sich Prozesse und Threads hauptsäch- lich durch die Art der Ressourcenteilung der Kindprozesse mit dem Elternprozess unterschei- den. Da die hier vorgestellten Programme und Bibliotheken unter Linux eingesetzt werden und Linux nur Prozesse unterstützt, ist die Nutzung von Threads zwangsläufig mit einer Emulation durch Prozesse verbunden.

14Vgl.:[RAUBER2007] S.101

(12)

Teil I

Grundlagen der parallelen Datenverarbeitung

In diesem Kapitel werden die theoretischen Grundlagen verschiedener Ansätze zur Paralleli- sierung von Algorithmen vorgestellt. Dabei werden konkrete Methoden, Konzepte und Umset- zungsmöglichkeiten gezeigt.

This chapter provides an introduction to the theory of parallel programming, concepts and techniques. It shows the most popular approaches, methods and concepts for parallelization of algorithms.

(13)

2 Stufen der Parallelisierung

Unter Parallelisierung wird die Zerlegung eines Problems in Teilprobleme verstanden, die gleich- zeitig von mehreren Prozessoren verarbeitet werden können, so dass die Berechnung weniger Zeit benötigt, als würde sie auf einem einzelnen Prozessor erfolgen. Auf diese Weise lässt sich ein gegebenes Problem in kürzerer Zeit oder aber ein größeres Problem in der selben Zeit lösen.

Es lassen sich vier Stufen der Parallelisierung unterschieden15, wobei sich die ersten drei Stu- fen Wortbreite, Pipelining und Superskalare Prozessoren direkt auf die verwendete Technik im Prozessorkern beziehen. Die letzte Stufe, Parallelisierung auf Prozessebene, ist eher ein pro- grammtechnisches Konstrukt, das nicht mehr direkt vom Prozessor abhängt16, sondern vom Betriebssystem übernommen wird.

Die Wortbreiteist der Anzahl der Bits, die in einer Operation vom Prozessor gleichzeitig ver- arbeitet werden können und entspricht somit der internen Busbreite und der Registergrösse.

Die Wortbreite bestimmt maßgeblich, wie viele Bytes bei einem Speicherzugriff gleichzeitig übertragen werden können. Aktuelle Prozessoren haben eine Wortbreite von 32 oder 64 Bit.

Eine Instruktion besteht aus mehreren atomaren Operationen, die in der Regel mindestens die folgenden Schritte umfasst:

1. fetch: Laden der nächsten Instruktion aus dem Speicher, 2. decode: Dekodieren der Instruktion,

3. execute: Bestimmung von Quell- und Zieladressen der Operanden und Ausführen der In- struktion,

4. write back: Zurückschreiben des Ergebnisses.

Unter Pipelining versteht man die Ausführung solcher atomaren Operationen durch separa- te Hardwareeinheiten, wodurch eine zeitlich überlappende Ausführung mehrerer Instruktionen möglich wird. Die Verarbeitung der nachfolgenden Instruktion kann im günstigsten Fall bereits mit der fetch-Operation beginnen, sobald die vorhergehende Instruktion die decode-Operation durchläuft. Dies funktioniert jedoch nur dann, wenn keine Abhängigkeiten zwischen den In- struktionen bestehen17.

Superskalare Prozessoren18erweitern das im Pipelining eingesetzte Konzept separater Hardwa- reeinheiten für atomare Operationen auf Instruktionsebene. Dazu verfügt der Prozessor über se- parate Funktionseinheiten für bestimmte Aufgaben, zum Beispiel für Ganzzahlarithmetik (ALU - arithmetic logical unit), Fließkommaarithmetik (FPU - floatin point unit) und Speicherzugriffe (MMU - memory management unit). Die Beschränkung der parallelen Ausführung hinsichtlich der Abhängigkeiten nachfolgender Instruktionen gelten auch hier.

Moderne Prozessoren enthalten darüber hinaus auch spezielle erweiterte Befehlssätze wie MMX (Multi-Media-Extension) oder SSE (Streaming SIMD Extension)19, die für die parallele Verar-

15Vgl.: [RAUBER2007] S.11

16Eine Abhängigkeit besteht insofern, dass der verwendete Prozessor eine virtuelle Speicheradressierung unter- stützt, was bereits mit der IA-32-Architektur eingeführt wurde. Dies schließt natürlich nicht aus, dass die Prozes- sortechnik Funktionen speziell für die Parallelisierung enthalten kann, wie z.B. Multi- und Hyperthreading.

17Siehe auch Abschnitt 4.1 auf Seite 13.

18Vgl.: [RAUBER2007] S.14ff.

19Intel: MMX ab Pentium, SSE ab Pentium III AMD: 3D-Now! ab K-6, SSE ab Athlon XP IBM/Motorola: VMX/AltiVec ab PowerPC 7400/G4

(14)

beitung größerer Datenmengen nach dem SIMD-Prinzip vorgesehen sind. Diese werden in der Regel als Technologie zur Beschleunigung von Multimedia-Applikationen angepriesen, lassen sich aber ebenso gut für sinnvolle Rechenaufgaben nutzen.

Die letzte Stufe der Parallelisierung auf Prozessebene ermögliche die parallele Ausführung mehrere Programme. Diese auch als Multitasking bezeichnete Konzept wird in erster Linie durch das Betriebssystem realisiert. Wenn man vom Parallelcomputing spricht, ist in der Regel eine solche Form der Parallelisierung von Algorithmen gemeint, wobei die Berechnung durch mehrere, parallel ausgeführte Prozesse erfolgt. Dies resultiert nur dann in einer kürzeren Be- rechnungszeit, wenn für jedes Programm auch ein eigener Prozessor zur Verfügung steht.

3 Parallele Architekturen

3.1 Flynnsche Klassifizierung

Die Flynnsche Klassifizierung beschreibt vier idealisierte Klassen von Parallelrechnern basie- rend auf der Anzahl separater Programmspeicher, Datenspeicher und Recheneinheiten sowie deren Abhängigkeiten untereinander. Flynn unterscheidet dabei:20

SISD Single Instruction - Single Data beschreibt einen sequentiellen Rechner, der jeweils ge- nau eine Anweisung auf genau einem Datenelement ausführt. Es existiert keine Parallelität.

MISD Multiple Instruction - Single Data ist ein Konzept, bei dem ein Datenelement nacheinan- der durch verschiedene Anweisungen verarbeitet wird. Dieses Konzept ist eher theoretisch, jedoch kann Pipelining als eine einfache Form von MISD interpretiert werden.

SIMD Single Instruction - Multiple Data entspricht der Verarbeitung mehrerer Datenelemente durch genau eine Anweisung. Dies ist bei Vektorrechnern der Fall, aber auch bei vielen Befehlssatzerweiterungen wie MMX oder SIMD.

MIMD Multiple Instruction - Multiple Data ist die Verarbeitung unterschiedlicher Datenele- mente durch jeweils unterschiedliche Anweisungen. Dies ist bei Superskalaren Prozessoren sowie Parallelrechnern der Fall, wobei verschiedene Funktionseinheiten oder Prozessoren parallel verschiedene Aufgaben ausführen.

Diese Klassifizierung lässt sich auch auf die Parallelisierung von Algorithmen anwenden, wobei jeder der als „Multiple” aufgeführten Aspekte einen potenziellen Kandidaten für eine Paralleli- sierung darstellt.

3.2 Speichermodelle

Aus logischer und physischer Sicht lassen sich Modelle mit gemeinsamem und verteiltem Spei- cher unterscheiden. Das physische Speichermodell hat großen Einfluss auf die Ausführungsge- schwindigkeit paralleler Programme, da es Latenz und Bandbreite bei Speicherzugriffen und Kommunikationsoperationen bestimmt.

20Vgl.: [HOFFMANN2008] S.11f., [RAUBER2007] S.17ff., [RAUBER2008] S.27f.

(15)

3.2.1 Rechner mit gemeinsamem Speicher

Bei gemeinsamem Speicher existiert ein für alle Prozessoren einheitlicher Adressraum. Ge- meinsamer Speicher stellt hohe Anforderungen an Synchronisations- und Konsistenzmechanis- men, um einen einheitlichen Speicherinhalt zu gewährleisten, was insbesondere zur Vermeidung von Race-Conditions bei konkurrierendem Schreib-Lese-Zugriffen notwendig ist.

Bei gemeinsamem Speicher kann der Speicherzugriff auf unterschiedliche Weise realisiert wer- den, abhängig davon, wie die Speicherbänke physisch organisiert sind. Der Datenaustausch zwischen Prozessoren und Speicherbänken erfolgt über einen sogenannten Interconnect. Dieser kann z.B. als Bus ausgelegt sein, so dass abwechselnd immer nur ein Prozessor exklusiven Zu- griff auf alle Speichermodule hat. Diese Architektur ist in der Regel bei Mehrkern-Prozessoren anzutreffen, die über einem gemeinsamen Adressbus mit dem Speicher-Controller kommunizie- ren. In diesem Fall ist die Zugriffsgeschwindigkeit stets gleich, daher spricht man von UMA- Architektur (Uniform Memory Access). Das Gegenstück hierzu bildet die NUMA-Architektur (Non-Uniform Memory Access), bei der jedem Prozessor ein eigenes Speichermodul zugeord- net ist, auf das demzufolge schneller zugegriffen werden kann als auf Module anderer Prozes- soren.21

Die physische Verteilung des Speichers muss nicht zwingend mit dem logischen Speichermo- dell übereinstimmen. So kann z.B. ein gemeinsamer Speicher auch über einen Netzwerkver- bund von Rechnern mit jeweils eigenem Speicher realisiert werden, wobei Adressumsetzung und Datenaustausch durch die jeweilige Programmierschnittstelle vorgenommen werden.

Abbildung 1: Gemeinsames Speichermodell UMA

Quelle: [BAUKE2006] S. 11

Abbildung 2: Gemeinsames Speichermodell NUMA

Quelle: [BAUKE2006] S. 12.

21Vgl.: [RAUBER2007] S. 25ff.

(16)

3.2.2 Rechner mit verteiltem Speicher

Verteilter Speicher bedeutet, dass alle Prozessoren einen eigenen, privaten Adressraum besit- zen. Für den Datenaustausch muss ein Verbindungsnetzwerk existieren, und er findet nur dann statt, wenn er explizit ausgelöst wird. Durch die entfallenden Synchronisationsmechanismen beim Speicherzugriff ermöglicht es diese Architektur, wesentlich mehr Rechner miteinander zu verbinden. Dies erfolgt allerdings auf Kosten der Übertragungsgeschwindigkeit von Daten zwischen den beteiligten Rechnern, was derartige Rechner für feingranulare Probleme wenig geeignet macht.22

Das Verbindungsnetzwerk hat erheblichen Einfluss auf die Geschwindigkeit. Die bestimmenden Faktoren sind Bandbreite und Latenz. Es kann davon ausgegangen werden, dass mit zunehmen- der physikalischer Entfernung zwischen den Rechnern die Latenz steigt und die Bandbreite sinkt.23

Weiterhin kann durch geschicktes Ausnutzen der Netzarchitektur die Geschwindigkeit von Datenverteilungs-Operationen wie Broadcast erhöht werden, wenn Nachbarschaftsbeziehungen ausgenutzt werden.24

Abbildung 3: Verbindungsnetzwerke

Quelle: [BAUKE2006] S.26

Durch die Verwendung von lokal zugeordneten Cache-Speichern25 entsteht das Problem der Cache-Kohärenz26, da hier lokale Kopien gemeinsamer Variablen vorgehalten werden. Die Än- derung einer Kopie muss nicht nur eine Aktualisierung des gemeinsamen Speichers, sondern

22Vgl.: [RAUBER2007] S.21ff.

23Vgl.: [RAUBER2007] Kapitel 2.5 Verbindungsnetzwerke, S. 32ff.

24Vgl.: [SANTORO2007] S. 32ff.

25Vgl.: [RAUBER2007] S.73ff.

26Vgl.: [RAUBER2007] S.31., S. 84ff.

(17)

auch eine Aktualisierung aller anderen Kopien zur Folge haben. Die Steuerung des Caching erfolgt durch einen eigenen Cache-Controller und ist sowohl für den Prozessor als auch aus Programmsicht transparent.27 Die Probleme des Cachings lassen sich auf höhere Ebene über- tragen, wenn es um die Entwicklung paralleler Programme und insbesondere von Bibliotheken für das verteilte Rechnen geht, da hier ebenfalls lokale und entfernte Daten synchronisiert wer- den müssen.

3.3 Prozesse / Threads

Als Prozesse werden Programme bezeichnet, die zu einem gegebenen Zeitpunkt ausgeführt werden. Ein Prozess besitzt dabei eine Prozessumgebung, die durch eine Datenstruktur im Be- triebssystem realisiert wird und zur Verwaltung des Zustandes sowie der Ressourcen eines Pro- zesses dient. Dazu gehören z.B. die Inhalte der Prozessorregister, verwendete Speicherbereiche, Umgebungsvariablen und geöffnete Dateien. Threads sind ebenfalls eine Form von Prozessen.

Sie unterscheiden sich von ’richtigen’ Prozessen nur dadurch, dass sie keinen exklusiven Zugriff auf ihre Ressourcen haben, sondern diese mit anderen Prozessen, insbesondere mit dem Eltern- Prozess, teilen. Prozesse werden unter Unix erzeugt, indem der laufende Prozess durch Aufruf einesfork()-Kommandos in seinem aktuellen Zustand dupliziert wird. Der so entstandene Kind- Prozess kann nun einen anderen Programmzweig ausführen als der Elternprozess, andere Daten berechnen oder seine Prozessumgebung durch die eines anderen Programms ersetzen.

Die Unterscheidung zwischen Prozessen und Threads dient hauptsächlich dazu, den physischen Ressourcenbedarf zu reduzieren, da beim Erzeugen eines Prozesses (theoretisch) dessen ge- samte Prozessumgebung (inklusive Speicherbereiche) dupliziert werden muss, was beim Erzeu- gen von Threads nicht der Fall ist. Threads besitzen somit per Definition einen gemeinsamen Adressraum mit dem Elternprozess, währen Prozesse eigene Adressräume besitzen. Allerdings gibt es Methoden, wie z.B. Shared Memory, durch die auch Prozesse auf gemeinsame Speicher- bereiche zugreifen können.

Letztendlich bilden Prozesse die Grundlage für parallele Programme. Ein paralleler Algorith- mus kann also bereits durch die Methoden, die für die Verwaltung von Prozessen sowie für die Interprozesskommunikation vom Betriebssystem bereitgestellt werden, realisiert werden.

Allerdings ist die komplette Logik zur Steuerung der einzelnen Prozesse explizit zu implemen- tieren, was zwar sehr viele Möglichkeiten zur Optimierung der Rechengeschwindigkeit, aber auch sehr viel Aufwand und hohe Fehleranfälligkeit bedeutet. Die Verwendung von speziell für diesen Zweck optimierten Bibliotheken ist häufig einfacher und auch effizienter.

3.4 Client-Server-Architekturen

Client-Server-Architekturen verwenden als logische Struktur ein Stern-Modell, wobei der Ser- ver im Zentrum steht und direkte Verbindungen mit allen Clients unterhält. Parallelisierung durch Client-Server-Architekturen werden durch das Master-Worker-Konzept umgesetzt, bei dem der Server (Master) Rechenaufgaben oder Daten an die verbundenen Clients (Worker) sen- det und diese das Resultat zurücksenden. Eine derartige Architektur lässt sich durch viele paral- lele Schnittstellen abbilden. Da die Abhängigkeiten zwischen den verbundenen Rechnern wenig

27Die Existenz eines Caches macht sich durch Unterschiede in der Geschwindigkeit von Speicherzugriffen bemerk- bar. Siehe dazu Kapitel 6.3.

(18)

komplex sind, ist diese Architektur relativ einfach zu implementieren und - sofern die physi- schen Ressourcen entsprechend dimensioniert sind - auch für sehr große Rechennetze höchst effektiv, wie z.B. das Seti@Home-Projekt zeigt.

3.5 Cluster-Computing

Die Idee des Cluster-Computings besteht darin, durch Verwendung handelsüblicher Kompo- nenten und freier Cluster-Software einen Parallelrechner mit verteiltem Speicher zu realisieren.

Durch die günstigen Kosten werden derartige Cluster häufig von Universitäten und Forschungs- einrichtungen eingesetzt.

Diese auch als Beowulf-Cluster28 bezeichneten Computer gehen auf das Beowulf-Projekt der NASA von 1994 zurück, bei dem 16 Linux-PCs mittels PVM29 zu einem Parallelrechner ver- bunden wurden.30

Jeder Rechner in einem Cluster wird als Knoten bezeichnet und kann wiederum selbst eine eige- ne parallele Architektur aufweisen. Beowulf-Cluster lassen sich sehr leicht skalieren, da hierfür lediglich weitere Knoten an das Netzwerk angeschlossen und mit der Cluster-Software verse- hen werden müssen. Auf diese Weise lassen sich sogar ältere Rechner noch sinnvoll verwenden.

Das Potential dieser Architektur zeigt sich darin, dass sich in Verbindung mit Hochleistungs- Netzwerken und moderner Rechentechnik Cluster bauen lassen, die zu den weltweit schnellsten Rechnern zählen. Die Tabelle 1 zeigt die weltweit fünf schnellsten Parallelrechner nach dem Linpack-Benchmark. Diese sind natürlich nicht mehr aus einzelnen PCs zusammengesetzt, son- dern bestehen aus Racks mit einer entsprechenden Anzahl von Einschüben, verwenden jedoch handelsübliche Großserientechnik.

Die Bedeutung freier Software für das Cluster-Computing zeigt sich daran, dass viele Hersteller auf eine Linux-Distribution zurückgreifen und diese nach Bedarf anpassen. Da der Quelltext der Programme frei verfügbar und veränderbar ist, können so zum Beispiel optimierte Kernel (z.B.

von Cray und IBM) zum Einsatz kommen.

3.6 Grid-Computing

Als Grid-Computing31 wird eine Form des Cluster-Computings bezeichnet, bei der eine we- sentlich losere Koppelung der Knoten zum Einsatz kommt. Ein derartiges Computing-Grid ist häufig geographisch weit verteilt.

Im deutschen Sprachraum wird häufig mit dem Begriff „Grid” ein regelmäßiges Gitter assoziiert und damit dem Grid-Computing seine Besonderheit durch Verwendung einer speziellen Topo- logie unterstellt. Tatsächlich weisen regelmäßige - und damit auch gitterförmige - Topologien manche Vorteile für Routingverfahren auf, in Wirklichkeit aber stammt die Bezeichnung „Grid”

vom Englischen Begriff für „Stromnetz” (power grid) ab und weist eine beliebige Netzstruktur im Allgemeinen - und auf das Internet im Speziellen - hin. Die Analogie zum Stromnetz ist, dass Ressourcen im Grid transparent zur Verfügung gestellt und durch einfachen Anschluss an das Grid abgerufen werden können.

28http://www.beowulf.org

29Siehe dazu Kapitel 10.4.

30Vgl.: [BAUKE2006] S.27f.

31Vgl.:[BARTH2006]

(19)

Tabelle 1: Linpack Top-5 Supercomputer Stand 06/2008

# System Standort Typ OS #Prozessoren GFlop/s

1. IBM

BladeCenter QS22/LS21

Cluster

LANL Cluster Linux 122.400

(PowerXCell 8i, AMD Opteron

Dual-Core)

1.026.000

2. IBM

eServer Blue Gene Solution

LLNL MPP Suse Linux

Enterprise Server 9 /

CNK

212.992 (PowerPC 440)

478.200

3. IBM

Blue Gene/P Solution

ANL MPP Suse Linux

Enterprise Server 9 /

CNK

163.840 (PowerPC 450)

450.300

4. Sun

Microsystems SunBlade

x6420

TACC Cluster Linux 62.978

(AMD x86_64 Opteron Quad

Core)

326.000

5. Cray Inc.

Cray XT4

ORNL MPP CNL 30.978

(AMD x86_64 Opteron Quad

Core)

205.000

Erläuterung:

LANL: Los Alamos National Laboratory, National Nuclear Security Administration LLNL: Lawrence Livermore National Laboratory, National Nuclear Security Administration ANL: Argonne National Laboratory

TACC: Texas Advanced Computing Center/Univ. of Texas, ORNL: Oak Ridge National Laboratory

CNK: Compute Node Kernel; von IBM angepasster Linux-Kernel CNL: Compute Node Linux von Cray Inc.

Quelle:http://www.top500.org/lists/2008/06, Stand 01.11.2008

Ein wichtiges Alleinstellungsmerkmal des Grid-Computing - vor allem im wissenschaftlichen Bereich - gegenüber anderen Formen des Vernetzen Rechnens ist die Bereitstellung der Res- sourcen auf volontärer Ebene. Dabei stellen die Teilnehmer freiwillig und kostenfrei nicht be- nötigte Rechenkapazität zur Verfügung, in sie ein Programm installieren, das mit niedriger Prio- rität ausgeführt wird und immer dann Berechnungen durchführt, wenn der Rechner nur gering ausgelastet ist.

(20)

4 Parallelisierungsebenen

Parallelisierung von Programmen kann auf verschiedenen konzeptionellen Ebenen erfolgen, für die es verschiedene Ansätze und Nebenbedingungen gibt.

4.1 Parallelität auf Instruktionsebene

Die am dichtesten an der Hardware angesiedelte Ebene, in der eine Parallelisierung möglich ist, ist die Instruktionsparallelität. Unter bestimmten Voraussetzungen kann die Ausführung von In- struktionen eines an sich sequentiellen Programms von einer dafür ausgelegten CPU optimiert und parallel durchgeführt werden. Dabei legt der Scheduler die Reihenfolge der auszuführenden Instruktionen fest. Die zu parallelisierenden Instruktionen dabei lediglich auf folgende Abhän- gigkeiten zu prüfen:32

1. Fluss-Abhängigkeit 2. Anti-Abhängigkeit 3. Ausgabe-Abhängigkeit

Die Prüfung der Abhängigkeiten beschränkt sich jeweils auf die Verwendung der CPU-Register durch die einzelnen Instruktionen. Besteht zwischen zwei Instruktionen keine dieser Abhängig- keiten, so können sie parallel ausgeführt werden.

Eine Fluss-Abhängigkeit besteht immer dann, wenn eine Instruktion A einen Wert in ein Re- gister lädt, das anschließend durch Instruktion B als Operand verwendet wird. In diesem Fall muss InstruktionAzwingend vor InstuktionBausgeführt werden. Umgekehrt besteht eine Anti- Abhängigkeit, wenn Instruktion Beinen Wert in ein Register lädt, dass InstruktionA als Ope- rand verwendet. Eine parallele oder umgekehrte Ausführungsreihenfolge führt in beiden Fällen dazu, dass falsche Operanden verwendet werden. Wenn beide Instruktionen das selbe Register zur Speicherung eines Ergebnisses verwenden, spricht man von Ausgabe-Abhängigkeit. Hier kann eine Parallelisierung dazu führen, dass eine nachfolgende Operation das falsche Ergebnis aus dem Register liest. Es tritt eine sogenannte Race-Condition ein, bei der das Ergebnis davon abhängt, welche Instruktion schneller ausgeführt wurde.

4.2 Parallelität auf Datenebene

Datenparallelität33 liegt immer dann vor, wenn eine Operation auf mehrere, voneinander un- abhängige Elemente oder Datenblöcke angewandt wird. Ein einfaches Beispiel hierfür ist eine Schleife, die ein Array mit Werten initialisiert:

for(int i=0; i<size; i++){

array[i]=0;

}

32Vgl.: [RAUBER2007] S.120f.

33Vgl.: [RAUBER2007] S.122f

(21)

Es ist in diesem Fall völlig unerheblich, in welcher Reihenfolge auf die einzelnen Array- Elemente zugegriffen wird, das Resultat ist stets dasselbe. Daher ließe sich die Berechnung in 1...sizeTeilschritte zerlegen, die parallel ausgeführt werden können. Ein anderes Beispiel ist die MatrizenmultiplikationA=B*C. Hier können alle Elemente der ErgebnismatrixAunabhän- gig voneinander berechnet werden. Tatsächlich stellt die Implementierung von Berechnungen als eine Reihe von Matrixoperationen eine der leichtesten Parallelisierungsmöglichkeiten dar, da für diese Operationen bereits parallele Verfahren existieren.34

4.3 Parallelität in Schleifen

Schleifen lassen sich parallelisieren, wenn zwischen einzelnen Iterationen keine Datenabhän- gigkeiten bestehen. Da dadurch die Reihenfolge der Iterationen unwichtig wird, kann jede Ite- ration unabhängig von den anderen ausgeführt werden.35 Dieser Ansatz wird beispielsweise durch OpenMP verfolgt.

Unter bestimmten Umständen lassen sich auch Schleifen parallelisieren, die Datenabhängigkei- ten enthalten. Voraussetzung hierfür ist, dass sich die einzelnen Iterationen in Gruppen aufteilen lassen, deren Resultate sich zu einem Gesamtergebnis zusammenfassen lassen. So kann z.B. die folgende Schleife:

for(int i=0; i<100; i++){

summe+=array[i];

}

in Teilschleifen aufgeteilt werden, deren Einzelresultate sich durch Addition zu einem Gesamt- ergebnis zusammenfassen lassen:

for(int i=0; i<50; i++){

summe1+=array[i];

}

for(int i=50; i<100; i++){

summe2+=array[i];

}

summe=summe1+summe2;

Ist eine derartige Aufteilung möglich, kann die ursprüngliche Schleife ebenfalls parallel aus- geführt werden. Derartige Konstrukte werden von verschiedenen parallelen Schnittstellen un- terstützt, wobei die lokalen Ergebnisvariablen (hier summe) nach Beendigung aller Schleifen- durchläufe unter Verwendung eines sogenannten Reduktionsoperators zusammengefasst wer- den.

4.4 Parallelität auf Funktionsebene

Bei der Verwendung rein funktionaler Programmiersprachen wie z.B. Haskell lassen sich alle Funktionsläufe parallel ausführen, da durch die Konzeption der Sprache Seiteneffekte ausge- schlossen sind. Funktionen bestehen dabei nur aus elementaren Operationen oder aus anderen

34Siehe Kapitel 10.2.

35Vgl.: [RAUBER2007]S.123ff.

(22)

Funktionen, besitzen Eingabe- und Rückgabewerte, lösen aber keine Aktionen aus. Somit ist ausgeschlossen, dass eine Funktion die Eingabedaten einer anderen Funktion manipuliert.

Dieses Konzept lässt sich auch auf nicht rein funktionale Programmiersprachen anwenden, so- fern für den parallelisierenden Teil ausschließlich Funktionen verwendet werden, die nur lokale Variablen verwenden. Dies entspricht der Zerlegung eines Programms sind unabhängige Tei- laufgaben, sogenannte Tasks.36

36Vgl.: [RAUBER2007]S.127ff.

(23)

5 Parallele Programmiermodelle

5.1 Darstellung

Die Darstellung der Parallelität innerhalb eines Programms kann an unterschiedlichen Stellen erfolgen. Es lässt sich hier grob zwischen impliziter und expliziter Darstellung unterscheiden, wobei sich jeweils weitere Detaillierungsgrade ableiten lassen.37

Implizite Darstellung

Die implizite Darstellung stellt sich aus Sicht eines Programmierers als einfachere Variante dar.

Die Programmierung erfolgt gewohnt in sequentieller Weise, die Parallelisierung wird durch den Compiler oder durch die Eigenschaften der verwendeten Programmiersprache selbst reali- siert.

Die Parallelisierung durch einen Compiler erfordert, dass der Programmablauf und die Verbin- dungen zwischen Variablen analysiert und auf Parallelisierbarkeit hin untersucht werden. Dies ist ein sehr komplexer Vorgang und die erzielbaren Resultate sind in der Regel nicht sehr gut.

Daher gibt es den Ansatz, im Quellcode Hinweise für den Compiler einzubetten, die Paralleli- sierbare Abschnitte anzeigen. Ein derartiger Ansatz - OpenMP - ist im Kapitel 9 beschrieben.

Eine weitere Möglichkeit der impliziten Darstellung kann zum Beispiel durch die Verwendung rein funktionaler Programmiersprachen wie Haskell geschehen. Eine Parallelisierung kann Er- folgen, indem Funktionen, die als Argumente in anderen Funktionen auftreten, parallel ausge- führt werden, da in rein funktionalen Programmiersprachen Seiteneffekte ausgeschlossen sind.

Explizite Darstellung

Die Varianten der expliziten Darstellung sind zahlreicher als die der impliziten, da es mehr Ein- flussmöglichkeiten auf die konkrete Umsetzung der Parallelisierung gibt, während sich die im- plizite Darstellung letztendlich auf eine sehr formale Beschreibung der Parallelität beschränkt.

Es lassen sich die folgenden vier Klassen unterscheiden:

1. Die Parallelität wird durch Konstrukte einer parallelen Programmiersprache (z.B. High Per- formance FORTRAN) oder durch Erweiterungen sequenzieller Programmiersprachen (z.B.

OpenMP) explizit dargestellt. Die konkrete Umsetzung der Parallelität erfolgt jedoch durch den Compiler.

2. Die Zerlegung eines Algorithmus in parallele Abschnitte wird ebenfalls explizit vorgenom- men, zum Beispiel durch Verwendung von mehreren Prozessen oder Threads. Die Aufteilung auf einzelne CPUs sowie die Kommunikation zwischen den Prozessen/Threads erfolgt durch den Compiler oder das Betriebssystem.

3. Die Zuordnung einzelner Prozesse/Threads zu den CPUs kann ebenfalls explizit vorgenom- men werden. Dies ist jedoch nur in Ausnahmefällen notwendig, da die Verteilung von Pro- zessen auf CPUs durch das Betriebssystem vorgenommen werden sollte.

4. Die Synchronisation zwischen Prozessen sowie die Kommunikation und der Datenaustausch können ebenfalls explizit dargestellt werden. Als Vorteil wird angesehen, dass diese Methode die Verwendung eines Standard-Compilers erlaubt und eine sehr effiziente, auf den Anwen- dungsfall abgestimmte Implementierung zulässt, die dafür jedoch einen gewissen Aufwand

37Vgl.: [RAUBER2007]S.128ff.

(24)

erfordert. Als Beispiel sind Message-Passing-Konzepte wie PVM und MPI zu nennen, auf die im Abschnitt 10.4 bzw. im Kapitel 8 genauer eingegangen wird.

5.2 Strukturierung

Die Aufgabenverteilung zwischen den Prozessen kann auf verschiedene Weise erfolgen.38Häu- fig eingesetzte Modelle sind:

Master-Worker: Hier wird die Arbeit durch ein oder mehrere Kindprozesse (Slaves) ausge- führt, die von einem Hauptprozess (Master) gestartet, kontrolliert und koordiniert werden.

Pipelining: Beim Pipelining werden einzelne Prozesse so miteinander verbunden, dass die Ausgabe eines Prozesses direkt als Eingabe des nachfolgenden Prozesses dient, wobei alle Prozesse gleichzeitig aktiv sind.

Client-Server: Dieses Modell entspricht in seiner Funktionsweise dem umgekehrten Master- Worker-Modell, mit dem zusätzlichen Unterschied, das es sich auf einen Netzwerkverbund bezieht und es mehrere Server geben kann. Die Rechenleistung wird durch den/die Server erbracht und von den Clients angefordert.

5.3 Datenverteilung und Kommunikation

Die verschiedenen Arten, wie Daten zwischen Tasks ausgetauscht werden, können unter einer Menge von Operationen zusammengefasst werden. Diese werden so oder in ähnlicher Form durch die meisten parallelen Sprachen und Bibliotheken implementiert. Dabei lassen sich prin- zipiell Einzel- und kollektive (globale) Operationen unterscheiden. Während erstere die asyn- chrone Kommunikation zwischen genau zwei Kommunikationspartnern beschreiben, werden letztere von alle beteiligten Einheiten gleichzeitig ausgeführt.39

5.3.1 Broadcast

Eine Broadcast-Operation verteilt DatenX, die einem TaskPzugeordnet sind, auf alle anderen Tasks, so dass jeder Task nach der Operation exakt die gleichen Daten besitzt.





P1 :X P2 : []

...

Pn: []





Broadcast

=⇒





P1 :X P2 :X

...

Pn:X





Eine Broadcast-Operation ließe sich auch mit nnachrichtenbasierten Einzeloperationen erzie- len. Das Zusammenfassen der Einzeloperationen in eine einzige Broadcast-Anweisung erlaubt es, dem zugrundeliegenden System eine effizientere Reihenfolge für das Verteilen der Daten zu organisieren, indem die zugrundeliegende Topologie das Verteilungsschema bestimmt. Kriteri- en sind die notwendige Anzahl von Schritten, bis die Daten komplett verteilt sind, und die dafür notwendige Anzahl von Nachrichten.

38Vgl.: [RAUBER2007] S.133f.

39Vgl.: [RAUBER2007] S.142ff.

(25)

Eine als Flooding bezeichnete Methode besteht darin, dass ausgehend von initiierenden Kno- ten, jeder Knoten die Daten genau einmal an alle benachbarten Knoten schickt, sobald er sie empfangen hat. Die maximale nötige Anzahl von Schritten entspricht hier dem Durchmesser des Graphen.40 Die Anzahl der Nachrichten hängt von der Topologie ab. Ist die Topologie bei- spielsweise ein kompletter Graph, genügt genau ein Schritt, da jeder Empfänger direkt erreicht werden kann.

Abbildung 4: Effiziente Broadcast-Operation

Quelle: [BAUKE2006] S.174

5.3.2 Scatter

Eine Scatter-Operation verteilt DatenX, die einem Prozess P zugeordnet sind, in Blöckenx : x ∈ X gleichmäßig auf alle Prozesse, so dass jeder Prozess eine eindeutige Teilmenge der ursprünglichen Daten hält. In der Regel wird eine direkte Zuordnung Prozess-Nummer = Block- Nummer vorgenommen, aber auch anderer Verteilungsmuster sind möglich.





P1 :X P2 : []

...

Pn: []





Scatter

=⇒





P1 :x1 P2 :x2

...

Pn :xn





5.3.3 Gather

Die Gather-Operation entspricht einer umgekehrten Scatter-Operation. Dabei werden die Blöcke x1...xn aller Prozesse im Datenbereich eines einzelnen Prozesses zusammengefasst. Sie wird als Gather-all-Operation bezeichnet, wenn das Zusammenfassen der Blöcke für jeden Prozess geschieht, die Prozesse also nach der Operation jeweils über alle Datenblöcke verfügen.





P1 :x1 P2 :x2

...

Pn :xn





Gather

=⇒





P1 : [x1, ..., xn] P2 :x2

...

Pn :xn





40Vgl.: [SANTORO2007] S.13f.

(26)





P1 :x1 P2 :x2

...

Pn:xn





Gather−All

=⇒





P1 : [x1, ..., xn] P2 : [x1, ..., xn]

...

Pn : [x1, ..., xn]





5.3.4 Reduktion

Eine Reduktions- oder Akkumulations-Operation führt eine Funktion f() über den Daten aller Prozesse aus und stellt das Ergebnis in einem Prozess zur Verfügung. Typischerweise werden für f() arithmetische Funktionen (Summe, Produkt, Durchschnitt) oder Vergleichoperationen (größtes Element, kleinstes Element) implementiert.





P1 :x1 P2 :x2

...

Pn:xn





Akkumulation

=⇒





P1 :f(x1, ..., xn) P2 :x2

...

Pn:xn





Der Sinn kollektiver Reduktionsfunktionen liegt ebenfalls in der Erzielung einer höheren Ge- schwindigkeit durch Verringerung der Anzahl notwendiger Kommunikationsschritte gegenüber der entsprechenden Anzahl von Einzeloperationen oder Synchronisierungsoperationen. Eine Akkumulationsfunktion muss sowohl kommutativ als auch assoziativ sein, da die Reihenfolge der Einzeloperationen nicht vorhergesagt werden kann.

Abbildung 5: Effiziente Akkumulations-Operation

Quelle: [BAUKE2006] S.185

5.4 Synchronisation

Eine parallele Ausführung bedeutet nicht, dass Programme auch synchron ausgeführt werden.

Neben unterschiedlichen Prozessorgeschwindigkeiten und der jeweiligen Prozessorauslastung gibt es eine Reihe von Störfaktoren, die Einfluss auf die tatsächliche Ausführungsgeschwindig- keit haben. Daher kann man nicht davon ausgehen, dass sich eine gemeinsame Ressource - wie zum Beispiel ein Speicherinhalt - in einem stets definierten Zustand befindet. Wenn ein Prozess einen Abschnitt erreicht, der einen definierten Zustand voraussetzt, muss dieser zunächst her- gestellt werden. Dies wird durch Synchronisationsmechanismen erreicht, die dafür sorgen, dass sich die zu synchronisierende Ressource zu einem bestimmten Zeitpunkt für jeden beteiligten

(27)

Prozess in einem definierten Zustand befindet. Beispielsweise stellt die Speichersynchronisati- on identische Speicherinhalte für alle Prozesse sicher, eine Ablaufsynchronisation sorgt dafür, dass alle parallelen Prozesse die exakt gleiche Stelle im Programmtext erreicht haben.

5.4.1 Kritische Abschnitte

Bei Race-Conditions ist der Zustand einer Ressource davon abhängig, welche Prozesse in wel- cher Reihenfolge darauf zugreifen. Insbesondere nicht-atomare Anweisungen, die während der Ausführung unterbrochen werden können, sind dafür anfällig. Solche Programmabschnitte wer- den als „Kritische Abschnitte” bezeichnet. Für die Koordinierung der Prozesse sind eine Reihe von Verfahren bekannt.41 Parallele Sprachen und Bibliotheken stellen in der Regel Möglich- keiten zum Kennzeichnen kritischer Abschnitte bereit, so dass der Programmierer keine eigene Zugriffssteuerung implementieren muss. Probleme bereiten nur solche kritischen Abschnitte, die vom Programmierer nicht als kritisch erkannt werden, da die dadurch resultierenden Pro- grammfehler sporadisch, an verschiedenen Programmstellen und schlecht reproduzierbar auf- treten können, was den Anschein zufälliger Fehler erzeugt. Weiterhin kann es vorkommen, dass optimierende Compiler Code erzeugen, der nicht der Ausführungsreihenfolge der Anweisungen im Quelltext entspricht.

5.4.2 Barrieren

Barrieren sind eine Methode der Ablaufsynchronisation. Sie stellen sicher, dass sich alle Pro- zesse zu einem bestimmten Zeitpunkt an der selben Stelle im Programmtext - der Barriere - be- finden. Nachdem alle Prozesse die blockierende Barriere erreicht haben, werden sie synchron fortgesetzt. Dabei kann es vorkommen, dass einzelne Prozesse sehr lange auf andere warten müssen. Nicht-blockierende Barrieren dagegen erlauben es einem Prozess, mit der Ausführung von Programmcode fortzufahren, der nicht von anderen Prozessen abhängig ist, sofern diese mindestens eine bestimmte Stelle im Programmcode erreicht haben. Auf diese Weise kann ein Performancegewinn erzielt werden, da die Wartezeiten verkürzt werden können.

5.4.3 Locks

Der konkurrierende Zugriff auf Ressourcen kann durch Locking-Mechanismen gesteuert wer- den. Locks stellen eine Möglichkeit dar, Race-Conditions zu vermeiden, da der Zugriff auf gemeinsame Ressourcen exklusiv erfolgt. Anders als kritische Abschnitte können Locks über verschiedene Programmteile hinweg aufrecht erhalten werden. So kann an einer Stelle ein Lock erzeugt und später an einer anderen Stelle wieder freigegeben werden. Die Verantwortung für die Freigabe eines Locks liegt allein beim Programmierer, daher ist die Verwendung potentiell Anfällig für Deadlock-Situationen.

41Vgl. hierzu: [CARVER2006] S. 46ff.

(28)

6 Einflussfaktoren Paralleler Programme

6.1 Parallele Skalierbarkeit

Durch Parallelisierung soll in der Regel ein Geschwindigkeitszuwachs in der Form erzielt wer- den, dass pro Zeiteinheit mehr Rechenoperationen durchgeführt werden. Ähnlich der Frage nach den Grenzkosten oder dem Grenznutzen in der BWL und VWL stellt sich auch hier die Frage, welcher Aufwand - vor allem in Form zusätzlicher Rechner oder Prozessoren - für eine Parallelisierung notwendig ist und in welchem Verhältnis dieser zum erzielten Geschwindig- keitsgewinn steht.

6.1.1 Speedup

Geht man davon aus, dass ein parallelisierbares Programm auf einem Prozessor die Rechenzeit T1 benötigt, so ist die Rechenzeit aufp Prozessoren im optimalen FallT1/p. Parallelisierbare Abschnitte machen in der Regel nur einen Teil des gesamten Programms aus, so dass ein be- stimmter Anteil der Rechenzeit immer für einen sequentiellen Teil verbraucht wird, der konstant ist. Durch Erhöhung der Parallelität nimmt im parallelen Teil die Rechenzeit pro Prozessor ab, was beabsichtigt ist, wodurch der relative Anteil der sequentiellen Abschnitte größer wird. Das führt dazu, dass eine obere Grenze für den erzielbaren Geschwindigkeitszuwachs durch Hin- zunahme eines weiteren Prozessor existiert. Dieser Effekt wird nach seinem Entdecker Gene Amdahl als Amdahl’sches Gesetz42bezeichnet.

Ist für Eingaben der Größe n die Rechenzeit auf einem Prozessor T1(n) und die Rechenzeit auf p Prozessoren Tp(n), so ergibt sich der theoretisch erzielbare Geschwindigkeitszuwachs (Speedup) aus:43

Sp(n) = T1(n)

Tp(n) (1)

Der höchste theoretisch erzielbare Speedup ist Sp(n) = p, was einem linear skalierenden Programm entspricht. In der Praxis kann jedoch ein Speedup Sp(n) > p auftreten, was als superlinearer Speedup bezeichnet wird. Dies kann dadurch eintreten, dass die Problemgröße bzw. Datenmenge pro Prozessor so klein wird, dass geschwindigkeitssteigernde Effekte durch Caching-Mechanismen eintreten44. Es ließe sich auch umgekehrt argumentieren, nämlich dass im Regelfall geschwindigkeitssenkende Effekte durch Verwendung langsamerer Komponenten außerhalb des schnellen Cache bei zu großen Datenmengen die Ursache sind.

6.1.2 Amdahl’sches Gesetz

Amdahl nimmt einen Faktorsf für den seriellen Anteil45 eines Programmlaufs an, so dass sich die parallele Rechenzeit aus der Summe des nicht parallelisierbaren Anteils und des paralleli-

42Vgl.: [CHAPMAN2008] S. 33f., [CHANDRA] S. 173f., [BAUKE2006] S.10ff., [RAUBER2008] S. 170ff., [RAUBER2007] S.37f., [HOFFMANN2008] S.13ff., [EMKARNIADAKIS2000] S.39f.

43Vgl.: [RAUBER2007] S.168

44Vgl.: [RAUBER2008] S.37, [RAUBER2007] S.169

45In der Literatur wird auch statt des seriellen Anteilsf der parallele Anteil verwendet. Der Teiler ist dann entspre- chend umzustellen.

(29)

sierbaren Anteils vonT1ergibt:

Tp(n) = f∗T1(n) + 1−f p T1(n)

Nach obiger Formel ergibt sich der nach Amdahl erzielbare Speedup als eine vonnunabhängige Größe, was als Amdahl’sches Gesetz bezeichnet wird:46

Sp(n) = T1(n)

f ∗T1(n) + 1−fp T1(n) {f ∈R|0≤f ≤1}{p∈N|p >0}

S(p) = 1

f+ 1−fp

(2)

Der in Abhängigkeit des Faktorsf erzielbare Speedup ist in Abbildung 6 dargestellt47. Im opti- malen Fall einer vollständigen Parallelisierbarkeit mit f=1.0 skaliert ein Programm linear, wäh- rend bereits für f=0.95 der Zuwachs sehr schnell und deutlich stagniert. In dieser Berechnung ist noch nicht berücksichtigt, dass mit höherer Parallelität der zusätzliche Aufwand für die Erzeu- gung von Threads/Prozessen sowie für die Synchronisation und den Datenaustausch ebenfalls ansteigt.

Abbildung 6: Parallele Skalierbarkeit nach Amdahl

Quelle: eigene Darstellung.

6.1.3 Gustafson-Gesetz

Neben dem hier beschriebenen Amdahl’schen Gesetz existieren eine Reihe von Varianten, die weitere Faktoren berücksichtigen. Dazu gehören Beispielsweise der in Abhängigkeit vonpstei-

46Vgl.: [RAUBER2007] S.170, [RAUBER2008] S.38, [EMKARNIADAKIS2000] S.79f.,

47Ein Rechner mit 16 Rechenkernen stellt dabei eher die untere Grenze heutiger Parallelrechner dar. Entsprechende Boards mit 4 Sockeln sowie Quad-Core-Prozessoren sind im normalen Handel erhältlich. Ein heutiger ’kleiner’

Supercomputer ist Beispielsweise der Cray CX1, der noch unter einem Schreibtisch Platz findet, und bis zu 16 Quad-Core CPUs enthält. Ein Cray XMT enthält bis zu 8096 CPUs. (http://www.cray.com)

(30)

gende Kommunikationsaufwand, wodurch bei großenpeine weitere Erhöhung zu einer Verrin- gerung des Speedup führt, wie in Abbildung 7 dargestellt.

Abbildung 7: Parallele Skalierbarkeit nach Amdahl

Quelle: [BAUKE2006] S.12

Eine weitere Variante besteht darin, den parallelisierbaren Anteil auch in Abhängigkeit von der Eingabegröße zu betrachten. Dabei wird eine konstante Ausführungszeit für den sequentiellen Teil angenommen, wodurch bei steigender Eingabegröße der sequentielle Anteil abnimmt. Das Amdahl’sche Gegenstück hierfür ist eine monoton sinkende Funktion f(p, n) >0anstelle des Faktorsf.

In der Betriebswirtschaft existieren prinzipiell zwei Möglichkeiten, um bei konstanten Ver- kaufszahlen den Gewinn und somit die Effizienz des Kapitaleinsatzes zu erhöhen: eine Er- höhung der Preise oder eine Senkung der Kosten. Um die Effizienz von Parallelisierungsmaß- nahmen zu erhöhten, gibt es ebenfalls zwei grundsätzliche Möglichkeiten: Verringerung der Rechenzeit durch mehr Prozessoren oder Erhöhung der Eingabegröße.

Die Verringerung der Rechenzeit durch steigende Prozessorzahlen ist durch die bisher beschrie- benen Gesetzmäßigkeiten limitiert. Weiterhin stellt sich die Frage, ob eine signifikante Verrin- gerung der Rechenzeit den dafür notwendigen zusätzlichen Aufwand überhaupt rechtfertigt, was in der Regel nur auf sehr zeitkritische oder aber sehr langwierige Berechnungen zutreffen dürfte. Ein alternatives Ziel stellt eine bei etwa gleichbleibender Rechenzeit erzielbare Erhö- hung der Eingabegröße dar. Als Beispiel soll hier eine Anfrage an eine Internet-Suchmaschine dienen. Wenn die Antwortzeit in einem akzeptablen Bereich von z.B. wenigen Sekunden liegt, hat eine weitere Verringerung der Antwortzeit im Verhältnis zur damit verbundenen Erhöhung der Rechenkapazität nur wenig Sinn, wohl aber die Vergrößerung der Suchraumes, um die Tref- ferzahl zu erhöhen oder die Trefferqualität zu verbessern.

Beim Gustafson-Gesetz48 wird die Eingabegröße berücksichtigt, indem von einer gegebenen parallelen LaufzeitTp(n)für ein Problem ausgegangen und diese in Relation zur hypothetischen sequentiellen Laufzeit T1(n) = f Tp(n) +p(1−f)Tp(n) gesetzt wird. In Anlehnung an die bisherige Notation ergibt sich daraus derskalierte Speedup:

Sp(n) = f Tp(n) +p(1−f)Tp(n)

Tp(n) =f+p(1−f) =p+ (1−p)f (3)

48Vgl.: [RAUBER2007] S. 171f., [RAUBER2008] S. 27f., [BAUKE2006] S.16, [HOFFMANN2008] S.16f.

(31)

In Abbildung 8 ist der Unterschied zwischen beiden Ansätzen für f=0.05 beispielhaft darge- stellt. Der fast lineare Speedup nach Gustafson beruht darauf, dass für ein gegebenes paralleles Problem die entsprechende rein sequentielle Rechenzeit durch die damit linear steigende Ein- gabegröße zunimmt, während Amdahls Ansatz ein gegebenes Problem auf einem einzelnen Rechner durch Parallelisierung schneller zu lösen versucht, was durch den stets geringer wer- denden parallelen Anteil eine asymptotische Funktion zur Folge hat.

Abbildung 8: Speedup Amdahl vs. Gustafson

Quelle: eigene Darstellung.

6.1.4 Karp-Flatt-Metrik

Nun lässt sich der Faktor f nur sehr schwer anhand theoretischer Überlegungen oder Quell- textanalysen bestimmen. Durch Messung lässt sich f jedoch für ein bestimmtes Problem und Programm empirisch feststellen. Ein solches Maß ist die Karp-Flatt-Metrik. Dabei wird für mehrerepder Wert vonT(p)experimentell bestimmt. Anschließend kann durch Amdahl’s Ge- setz der entprechende empirische Anteilf bestimmt werden:49

f = 1/Sp(n)− 1p 1− 1p

Anhand des Verhaltens dieses Wertes zu p lässt sich aussagen, ob der Speedup eher vom se- quentiellen Anteil oder vom durch die Parallelisierung induzierten Rechenaufwand (Overhead) bestimmt wird. Letzteres ist daran zu erkennen, dass f mit steigender Prozessorzahl zunimmt, wodurch auch der Speedup langsamer steigt, als durch Amdahl’s Gesetz beschrieben.

Die Effizienz der Parallelisierung lässt sich aus dem Verhältnis zwischen Prozessor-Anzahl p und dem dadurch erzielten SpeedupS(p)bestimmen:

49Vgl.: [BAUKE2006] S.16f.

Referenzen

ÄHNLICHE DOKUMENTE

Ziel: Analyse der Kunden oder Fälle Analyse der Kunden oder Fälle Typ: Typ: Klassifikation Klassifikation..

Fast alle der Unternehmen, bei denen Data Mining-Techniken angewandt werden, wollen in Zukunft diesen Einsatz noch erhöhen, und 87% dieser Unternehmen berichten über eine

•kann auch alleine für Data Mining- oder OLAP- Zwecke genutzt werden.. Der Data Mining Prozess

Entferne Kandidaten Item-Mengen, die nicht häufig auftretende Teilmengen der Länge k enthalten. Ermittle den Support

A) Es werden oft Windeln gekauft. B) Der Kauf von Windeln führt zum Kauf von Bier.. B) Der Kauf von Windeln führt zum Kauf

Beim Web Mining (vgl. Kapitel 4.2) kommt die Analyse von se- mistrukturierten Texten zum Einsatz, die auf die Tags einer Auszeichnungsspra- che wie HTML zugreift. Zeitreihen

Nun wird einfach ein Knopf gedrückt gehalten und die SuS können über den Beamer den Vorgang erkennen.. Beobachtung: Es kann ein blaues Licht

“YouTube eine weltweite, nicht-exklusive und gebührenfreie Lizenz ein (mit dem Recht der Unterlizenzierung) bezüglich der Nutzung, der Reproduktion, dem Vertrieb,