Cluster Computing

Seminar:
Rechnerverbunde / Cluster Computing
und Anwendungsbeispiel
Johannes Krafft
Bodo Brand
Thorsten Blank
Betreuer: Prof. Dr. Rainer Werthebach
Hochschule Aalen
Sommersemester 2016
Ehrenwörtliche Erklärung
Wir versichern hiermit, dass wir unsere Seminararbeit mit dem Thema »Rechnerverbunde /
Cluster Computing« selbständig verfasst und keine anderen als die angegebenen Quellen und
Hilfsmittel benutzt haben.
Bodo Brand, Thorsten Blank, Johannes Krafft
1
Zusammenfassung
In dieser Arbeit behandeln wir die Grundlagen von Cluster Computing und erläutern einige
Konzepte der Parallelität in den beiden Gebieten Hardware und Software. Dazu grenzen wir
zunächst den Begriff »Cluster Computing« von anderen Begriffen und Themen ab und führen
dann Anwendungszwecke von Clustern aus. Anschließend wird auf die Hardware von Clustern
eingegangen und es werden Vor- und Nachteile von unterschiedlichen Methoden erläutert.
Dabei kommt ein Clustereigenbau zum Einsatz, worauf wir einen Hashcracker implementiert
haben, um die Schwierigkeiten von paralleler Programmierung zu erforschen.
MPP Massively Parallel Processor
MPI Message Passing Interface
SSH Secure Shell
HPC High-Performance Computing
SMB Server Message Block
NFS Network Filesystem
RAID Redundant Array of Inexpensive Disks
1
Abbildungsverzeichnis
3.1
3.2
3.3
3.4
3.5
3.6
Ein Setup ohne Failover-Funktionalität . . . . . . . . . . .
Beispiel-Setup eines Failover-Clusters . . . . . . . . . . . .
Load-Balancer . . . . . . . . . . . . . . . . . . . . . . . . .
Zentralisiertes Session-Managment . . . . . . . . . . . . .
Asynchrones Session-Managment . . . . . . . . . . . . . .
Bestimmung der optimalen Prozessoranzahl nach Amdahl
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
10
10
12
12
14
4.1
4.2
4.3
4.4
4.5
Stromverbrauch ARM und X86/64 Prozessoren.
Leistung von ARM und X86 . . . . . . . . . . .
HA-Cluster mit zwei Knoten . . . . . . . . . . .
Netzwerktypen . . . . . . . . . . . . . . . . . .
Unterschied bei Ethernet und SCI oder Myrine
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
17
18
19
20
20
5.1
Hello World Beispiel mit MPI unter C . . . . . . . . . . . . . . . . . . . . . . . 24
6.1
6.2
6.3
6.4
Versuchsaufbau für einen experimentellen Cluster
Parallelisierungsansatz MPI Hashcracker . . . . .
2. Parallelisierungsansatz MPI Hashcracker . . .
Finaler Parallelisierungsansatz MPI Hashcracker
7.1
Geschwindigkeitsvergleich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
25
26
27
28
Inhaltsverzeichnis
1 Einleitung (Bodo Brand)
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Ziel der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
5
5
2 Grundlagen Cluster Computing (Bodo Brand)
2.1 Definition Computer Cluster . . . . . . . . . . . . .
2.2 Abgrenzung von Begriffen und Verwendungszwecke
2.2.1 Supercomputer . . . . . . . . . . . . . . . .
2.2.2 Massively Parallel Processor . . . . . . . . .
2.2.3 Grid-Computing . . . . . . . . . . . . . . .
2.2.4 Cloud-Computing . . . . . . . . . . . . . . .
.
.
.
.
.
.
6
6
6
6
6
7
7
3 Verwendungszwecke(Johannes Krafft)
3.1 Workstation Cluster . . . . . . . . . .
3.2 Hochverfügbarkeitscluster . . . . . . .
3.3 Load-Balancing-Cluster . . . . . . . .
3.4 High Performance Computing Cluster
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
8
8
9
11
4 Hardware (Thorsten Blank)
4.1 Prozessor . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Festplatten Speicher . . . . . . . . . . . . . . . . . . . . .
4.2.1 Speicherlose Knoten . . . . . . . . . . . . . . . . .
4.2.2 Knoten mit jeweils eigenem und geteiltem Speicher
4.2.3 Knoten mit eigenem Speicher . . . . . . . . . . . .
4.3 Netzwerk . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
16
16
16
17
18
18
.
.
.
.
.
.
.
22
22
22
22
23
23
23
24
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Implementation
5.1 Betriebssysteme (Johannes Krafft) . . . . . .
5.1.1 Windows HPC . . . . . . . . . . . . .
5.1.2 Linux . . . . . . . . . . . . . . . . . .
5.2 Message Passing Interface (Bodo Brand) . . .
5.2.1 Einführung . . . . . . . . . . . . . . .
5.2.2 Programmiergrundlagen mit MPICH2
5.2.3 MPI Implementationen Vergleich . . .
3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6 Anwendungsbeispiel (Bodo Brand)
6.1 Wahl der Hardwarearchitektur . .
6.2 Wahl der MPI Implementierung . .
6.3 Installation und Konfiguration . . .
6.4 Anwendungsfall Hashcracker . . . .
6.4.1 Einführung . . . . . . . . .
6.4.2 Umsetzung . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
7 Geschwindigkeit (Bodo Brand)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
25
25
25
26
26
26
26
29
8 Zusammenfassung und Ausblick (Bodo Brand)
31
8.1 Erreichte Ergebnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4
Kapitel 1
Einleitung (Bodo Brand)
1.1
Motivation
Cluster Computer werden heutzutage in vielen Gebieten eingesetzt. Organisationen wie Hochschulen, Firmen und Forschungseinrichtungen benutzen diese in den unterschiedlichsten Gebieten. So kann ein Computer Cluster genutzt werden, um die Forschung bei Genomen, in
der Meteorologie, Physik, Chemie oder bei der Herstellung von neuen Materialien zu unterstützen[1]. Computer Cluster können auch verschiedene Serviceleistungen einer großen Anzahl
von Menschen zur Verfügung stellen. Die Möglichkeiten von Simulationen und Experimenten
sind endlos.
1.2
Ziel der Arbeit
Das Ziel der Arbeit ist es, die Funktionsweise eines Cluster Computers und deren Verwendungszwecke und Programmierschnittstellen zu verstehen und verständlich niederzuschreiben.
Zudem wollen wir anhand eines eigenen Clusters, die Hardware und Software Komponenten
installieren und eigene Software schreiben, um mit den Schwierigkeiten von paralleler Programmierung zu experimentieren und diese in dieser Arbeit teilen.
1.3
Vorgehen
Als erstes haben wir nach einem Einführenden Gespräch von unserem betreuenden Prof. Dr.
Rainer Werthebach einen Computer Cluster aus 4 Raspberry Pis erhalten, welchen wir mit
entsprechender Software ausgerüstet haben. Durch Brainstorming haben wir schließlich nach
Anwendungsfällen gesucht, welche Software wir für diesen Cluster implementieren wollen und
haben uns für einen Hashcracker entschieden. Um die Implementation zu bewerkstelligen,
suchten wir nach Tutorials, welche die Funktionsweise des parallelen Programmierens mit
dem Message Passing Interface genau genug erläutern. Durch das Wissen aus dem Tutorial
wurde dann der Hashcracker in Eigenproduktion erstellt.
Um die Grundlagen und Methoden von Cluster Computing zu verstehen, haben wir nach
einem entsprechenden Büchern recherchiert, welches das Themen Gebiet Cluster Computing
möglichst gut abdecken.
5
Kapitel 2
Grundlagen Cluster Computing (Bodo
Brand)
2.1
Definition Computer Cluster
Ein Cluster ist eine Ansammlung von Dingen vom selben Typ, welches wächst und nahe
beieinander erscheint [2]. Somit ist ein Computer Cluster ein Verbund aus mehreren Computern, welche zu einer Einheit verschmelzen. Die Computer werden dabei über ein Netzwerk
verbunden und bieten je nach Einsatzgebiet mehr Geschwindigkeit, mehr Kapazität, bessere Datenintegrität, höhere Zuverlässigkeit und mehr Verfügbarkeit von Ressourcen, als ein
herkömmlicher Computer [3]. Alle Rechnerknoten in einem Cluster haben dabei oft dieselbe Ausstattung an Hardware [4]. Neben diesen homogenen Clustern gibt es auch heterogene
Cluster, die aus verschiedenen Betriebssystemen und Hardware bestehen [5].
2.2
2.2.1
Abgrenzung von Begriffen und Verwendungszwecke
Supercomputer
Wie Jan Christian Meyer zu »What is the difference between a supercomputer and a computer
cluster?«[6] schreibt, ist der Begriff Supercomputer ein Überbegriff für alle Computer, die
Probleme lösen können, die so viel Rechenleistung benötigen, wie sonst kaum ein anderer
Computer zu einer bestimmten Zeit. Die Art von Supercomputer kann sich über die Zeit
ändern. So gibt es momentan viele Supercomputer vom Typ Cluster und MPP1 [7].
2.2.2
Massively Parallel Processor
Ein MPP ist ein Computer, der stark zusammenhängende Komponenten hat, um parallele
Rechnungen durchzuführen. Im Vergleich zu einem Cluster Computer, wie in Stackoverflow
beschrieben [8], können die CPUs nicht voneinander getrennt laufen, sondern die gesamte
Maschine wird als ein Computer angesehen. Da der Zusammenhang so stark ist, kann ein
schneller Austausch zwischen den CPUs stattfinden.
1
Massively Parallel Processor
6
2.2.3
Grid-Computing
Der Begriff Grid wird von dem englischen Begriff »Electrical Power Grid« abgeleitet, welches übersetzt Stromnetz heißt [9]. Die Idee dahinter ist, die Ressourcen unterschiedlicher
Nutzer zu nutzen, wie Strom aus der Steckdose [9]. Somit verbindet Grid-Computing mehrere Computer an unterschiedlichen geografischen Stellen zusammen, um hohe Rechenleistung
und Speicherkapazität zu erreichen. Dabei ist die Hardware der einzelnen Knotenpunkte im
Vergleich zu einem Cluster Computer und MPP typischerweise heterogen [4]. Grids werden
vornehmlich von einer bestimmten Gruppe von Nutzern aufgebaut und eingesetzt, die ein gemeinsames Vorhaben, z.B. die Durchführung wissenschaftlicher Simulationsexperimente, eint
[10]. Dabei können unterschiedliche Gesellschaften verknüpft werden und zusammenarbeiten.
So wurde 1997 versucht, den Supercomputer »High Performance Computing Center Stuttgart«
mit dem »Pittsburgh Supercomputing Centre« zu verbinden [9]. Wenn man zwei Cluster Computer verbindet, muss zudem eine hohe Anforderung an Sicherheit gewährleistet werden, da
die Verbindung zwischen den zwei Clustern meist mit unsicheren Netzen verbunden ist [11].
2.2.4
Cloud-Computing
Cloud-Computing bezieht sich sowohl auf die Applikationen, die als Service über das Internet
bereitgestellt werden, als auch auf die Hardware und Systemsoftware in den Datencentern,
welche diesen Service bereitstellen. Die Hardware und Software des Datencenters ist dabei das,
was wir als Cloud bezeichnen [12, S. 1]. So werden Dienstleistungen, wie Rechenleistung und
Speicherkapazität, zur Verfügung gestellt und je nach Verbrauch abgerechnet. Im Vergleich zu
Grid-Computing ist Cloud-Computing zentralisiert und wird lediglich von einer Gesellschaft
betrieben [4].
7
Kapitel 3
Verwendungszwecke(Johannes Krafft)
Die Verwendungszwecke von Computerclustern sind vielseitig. Einige populäre Anwendungsbeispiele sollen in diesem Kapitel vorgestellt werden.
3.1
Workstation Cluster
Das Ziel eines Workstation-Clusters ist eine »Einheitliche Arbeitsumgebung unabhängig vom
Arbeitsplatz« zu schaffen, sowie einen »Geringer[en] Administrationsaufwand durch Homogenität der Maschinen« zu erzielen [13]. Zu einem Workstation-Cluster gehört üblicherweise eine
zentrale Benutzerverwaltung, zentrale Benutzerverzeichnisse, zentrale Softwareverwaltung, ein
zentrales Konfigurationsmanagment und automatisierte Installationsprozesse [13].
3.2
Hochverfügbarkeitscluster
Der Großteil der Serviceanbieter im Internet sind darauf angewiesen, dass ihre Dienste ohne
Unterbrechung immer und überall erreichbar sind. Das Aussetzen einzelner Services, Softwareoder Hardwarekomponenten kann bei solchen Diensten schnell zum Totalausfall führen. Angenommen eine Webserver-Applikation läuft nur auf einem Server. Es reicht wenn eine Komponente ausfällt und die gehostete Webseite ist nicht mehr verfügbar (siehe Abbildung 3.1). Auch
Wartungsarbeiten am Server wie ein Betriebssystem- oder Softwareupdate führen zwangsläufig zu kurzer Downtime. [14]
Die Lösung für dieses Problem ist das Einrichten eines Hochverfügbarkeitsclusters (engl.
Failover-Cluster). Das Konzept: Wichtige Komponenten in einem System werden mehrfach
vorgesehen. Wenn eine Komponente ausfällt, wird ihre Aufgabe von einer anderen übernommen. Für jeden aktiven Server, der einen Dienst bereitstellt, muss mindestens ein äquivalenter
Standby-Server vorgesehen sein, der einspringt, wenn der Dienst auf dem aktiven Server nicht
mehr erreichbar ist.[14]
Es gibt zwei Mechanismen, wie der Standby-Server feststellen kann, ob er übernehmen
muss:
• Push Heartbeats: Der aktive Server sendet regelmäßig ein Signal an den StandbyServer. Wenn der Standby-Server für eine bestimmten Zeitraum kein Signal erhält, geht
8
Abbildung 3.1: Ein Setup ohne Failover-Funktionalität: Es reicht das eine Komponente ausfällt
um den Dienst für den Client unerreichbar zu machen. [14]
er davon aus das der Dienst auf dem aktiven Server momentan nicht verfügbar ist, und
übernimmt selbst die Rolle des aktiven Servers.
• Pull Heartbeats: Der Standby-Server sendet regelmäßig Anfragen an den aktiven Server. Wenn er für einen bestimmten Zeitraum keine Antwort auf seine Anfragen erhält,
übernimmt er.
Heartbeats können auf verschiedenen OSI-Schichten eingesetzt werden. [14] Zum Beispiel könnte man auf IP-Ebene die Verbindung des Servers mit dem Internet prüfen und auf Anwendungsebene den Status der Software.
Die große Frage ist, wie man die Standby-Server immer auf dem aktuellen Stand hält,
sodass sie jederzeit einsatzbereit sind. Laut [14] gibt es drei Ansätze, dies zu gewährleisten:
• Transaction log: Der aktive Server logged alle Änderungen mit. In regelmäßigen Abständen lesen die Standby-Server den Log ein und holen die Änderungen nach.
• Hot standby: Änderungen am aktiven Server werden sofort auch auf dem StandbyServer vorgenommen. Alle Server sind somit immer auf dem aktuellen Stand.
• Shared storage: Die Server teilen sich alle einen gemeinsamen Speicher, und sind somit
automatisch immer auf dem aktuellen Stand. (siehe Abbildung 3.2)
Es ist wichtig, das immer nur ein Server eines Dienstes aktiv ist. Verklemmungen oder
korrupte Daten sind sonst vorprogrammiert. Gewährleistet werden kann das mit einem Token,
der den aktiven Server als solchen markiert. Bevor sich ein Server aktiv schaltet, muss er im
Cluster prüfen, ob nicht ein anderer schon aktiv ist.[14]
3.3
Load-Balancing-Cluster
Wenn ein Webservice erfolgreich ist und somit stark gefragt, benötigt der Anbieter enorme
Rechenleistung, um dem Ansturm gewachsen zu sein. Ein einzelner Server kann nur eine
bestimmte Anzahl an Anfragen bearbeiten. Die logische Konsequenz scheint zu sein, den Server
aufzurüsten. Doch jede Architektur hat seine Limits.
Die Lösung ist die Einrichtung eines Load-Balancing-Clusters. Das Prinzip: Die einkommenden
9
Abbildung 3.2: Beispiel-Setup eines Failover-Clusters: Heartbeats stellen die Funktionsfähigkeit des Aktiven Servers fest. Beide Server greifen auf eine gemeinsamen Speicher (Shared
Storage) zu. [14]
Abbildung 3.3: Ein Load-Balancer verteilt die Anfragen der Clients an die Server. [14]
Anfragen werden auf mehrere, identische Server verteilt, um bei großem Ansturm trotzdem
verfügbar zu sein (siehe Abbildung 3.3). Wenn mehr Anfragen bearbeitet werden müssen, muss
schlicht und einfach ein weiterer Klon des Servers hinzugeschalten werden.[15]
Ein Load-Balancer ist eine Komponente die einkommende Anfragen an die Server im Cluster weiterleitet. Es werden verschiedene Algorithmen verwendet, um die Anfragen möglichst
optimal zu verteilen.
• Round-Robin Algorithmus: Alle Anfragen werden gleichmäßig auf alle Server verteilt, ungeachtet wie viele Anfragen ein Server aktuell schon bearbeitet. Es ist wichtig,
dass alle Server gleich stark sind, ansonsten würde ein Teil immer überlastet sein während der andere Teil der Server nie seine ganze Leistung nutzen würde.
• Weighted Round-Robin Algorithmus: Es wird die Rechenleistung der einzelnen
10
Server mit in Betracht gezogen, wenn die Anfragen verteilt werden. Der Serveradministrator schätzt die Leistung der Server, entsprechend dieser Schätzung werden die
Anfragen verteilt, sodass jeder Server prozentual gleich belastet wird.
• Least-Connection Algorithmus: Eine neue einkommende Verbindungsanfrage wird
immer an den Server weitergeleitet, der die geringste Anzahl an momentan offenen Verbindungen hat.
• Load-Base Algorithmus: Einkommende Anfragen werden an den Server mit der in
diesem Moment geringsten Auslastung weitergeleitet.
Manche Load-Balancer haben auch noch eine Failover-Funktionalität, d.h. sie leiten keine Anfragen an Server weiter, die nicht mehr reagieren.[15]
Wenn man die Anfragen so verteilt, tritt allerdings ein Problem auf: Ein Client muss möglicherweise in einer späteren Anfrage wieder erkannt werden und dementsprechend anders
behandelt werden. Normalerweise sind die folgenden drei Methoden zum Speichern dieser
benutzerbezogenen Informationen in einer sogenannten Session üblich:
• Der Client speichert die Session Informationen, z.B. in einem Cookie in seinem Browser.
• Die Daten werden auf dem Server gespeichert, der die Anfrage bearbeitet.
• Die Session Daten werden zusammen mit den anderen Nutzerdaten auf einem gemeinsamen Datenbankserver gespeichert.
Die mittlere Möglichkeit funktioniert in Verbindung mit Load-Balancing nicht. Der Nutzer
könnte bei der nächsten Anfrage an einen anderen Server geleitet werden, der ihn dann nicht
wiedererkennt. Der Load-Balancer muss die Anfragen eines Clients also immer an den gleichen
Server leiten.
Das führt allerdings dazu, dass die Ausfallsicherheit für die Session dieses Clients nicht mehr
gewährleistet ist, wenn der Server mit seiner Session ausfällt.
Die Session-Daten können in der Konsequenz nicht auf dem Server gespeichert werden, sondern in einem eigenen, ausfallsicheren System. Das Load-Balancing Cluster greift also auf ein
Hochverfügbarkeitscluster zu, in dem die Sessions gespeichert sind (engl. centralized state managment). (siehe Abbildung 3.4) Eine kostengünstigere Alternative wäre es, die Session Daten
immer zwischen allen Servern zu synchronisieren, so dass jeder Server im Load-BalancingCluster immer alle Sessions kennt. (engl. asynchronous session state management) (siehe Abbildung 3.5)[15]
3.4
High Performance Computing Cluster
Der wohl bekannteste Einsatz von Clustern ist die Verwendung als »Supercomputer«. Beispiele
für Einsatzgebiete sind:
• Wettersimulation
• Strömungssimulation
• Virtuelle Crashtests
• Chemische Simulation
11
Abbildung 3.4: Zentralisiertes Session-Managment [14]
Abbildung 3.5: Asynchrones Session-Managment [14]
12
• Kompilieren von Sourcecode
[16] [17] Allen Beispielen gemeinsam ist ein enorm hoher Rechenaufwand. Ein normaler Heimcomputer würde viel zu lange an diesen Problemen rechnen. Die naheliegenste Lösung scheint
zu sein, einfach eine schnelleren Prozessor zu entwickeln, um die Daten schneller verarbeiten
zu können. Das ist jedoch nur auf den ersten Blick sinnvoll: Ein Prozessor verarbeitet Daten.
Diese Daten müssen von irgendwo geladen und irgendwohin gespeichert werden. Wenn ein
Prozessor schneller wird, müssen auch die Daten schneller herbeigeschafft werden. Die Daten
können allerdings maximal mit Lichtgeschwindigkeit an den Prozessor geliefert werden. Es ist
daher nicht möglich, mit immer schnelleren Prozessoren Berechnungen unendlich zu beschleunigen. Die Lösung ist, mit mehreren schwächeren Prozessoren gleichzeitig parallel an dem
Problem zu arbeiten. Jeder einzelne Prozessor muss dadurch verhältnismäßig weniger Daten
verarbeiten. [11, S. 4]
Sei p die Anzahl der Prozessoren und π die Gesamtdauer der zu parallelisierenden Berechnung.
Naiv könnte man folgende Formel über die Laufzeit der Berechnung aufstellen:
T (p) =
π
p
(3.1)
Allerdings gibt es laut Amdahls Gesetz zwei Faktoren, die beim parallelisieren von Berechnungen beschränken. Zum einen können nicht alle Teile einer Berechnung parallelisiert werden.
Selbst wenn der parallelisierte Teil der Berechnung gegen null konvergiert, gibt der sequentielle Teil σ somit die untere Schranke der Laufzeit an. Zum anderen müssen die Prozessoren
während der Berechnung auch untereinander Informationen austauschen. Mit zunehmender
Prozessorzahl nimmt der Kommunikationsaufwand zwischen den Prozessoren immer mehr
Zeit in Anspruch. Ein Kommunikationsaufwand Tc abhängig von der Prozessorzahl bremst
somit die Rechenzeit:
T (p) = σ +
π
+ Tc (p)
p
(3.2)
Das Problem: Ab einer bestimmten Anzahl von Kernen wird der Kommunikationsaufwand
so groß, dass die gesamte Berechnungszeit wieder zunimmt. Bei einem sequentiellen Anteil von
1ZE, einem parallelisierbaren Anteil von 10ZE und einem Kommunikationsaufwand von 0.5 ZE
pro Prozessor ergibt sich beispielsweise eine optimale Prozessoranzahl von 4,5. (siehe Grafik
3.6) Aus dieser Erkenntnis muss der Schluss gezogen werden, dass sich mit dem Parallelisieren
von einem Problem dieses sich nicht beliebig schnell berechnen lässt, aber das mit zunehmender Anzahl von Prozessoren zunehmend große Probleme effizient gelöst werden können. Es ist
trotz allem immer noch wichtig den Kommunikationsoverhead möglichst gering zu halten. Bei
der Größe eines Teilproblems spricht man von Granularität oder Körnigkeit. Um den Kommunikationsaufwand gering zu halten, gilt es eine möglichst grobe Granularität zu verwenden,
d.h. möglichst große Teilprobleme in einem Stück zu berechnen, da feingranulare Programme
sehr viel Zeit auf Kommunikation verwenden müssen. [11, S. 10-12]
Die gerade erläuterte Theorie zur Parallelisierung von Problemen bezieht sich grundsätzlich
erst einmal nicht nur auf Computer-Cluster. Moderne CPUs besitzen bis zu 8 oder mehr Prozessorkerne, die unabhängig voneinander rechnen. Auch ist es möglich, mehrere CPUs auf
einem Motherboard mit gemeinsamem Speicher unterzubringen. Laut Bauke und Mertens ist
jedoch ein PC mit vier Prozessoren deutlich teurer als vier PCs mit je einem Prozessor, da
»Der ungebremste Zugriff auf den gemeinsamen Speicher (und andere gemeinsam genutzte
13
Abbildung 3.6: Bestimmung der optimalen Prozessoranzahl nach Amdahl
Komponenten) [...] eine aufwändige Elektronik [erfordert], und der Aufwand [...] schnell mit
der Anzahl der Prozessoren [steigt]. [...] Multiprozessoren kommen deshalb für massiv parallele
Anwendungen nicht in Frage.« [11, S. 23] Die Konsequenz ist der Verzicht auf gemeinsamen
Hauptspeicher, was dann auf die Bildung eines Computerclusters hinausläuft. [11, S. 21-23]
14
Kapitel 4
Hardware (Thorsten Blank)
Cluster können aus so gut wie jedem Computer mit Netzwerkschnittstelle erstellt werden. So
gibt es bereits Cluster, welche aus Spielkonsolen wie der XBOX erstellt wurden [18]. Diese
Konsolen unterscheiden sich in der Hardware wenig von handelsüblichen PCs und stellen eine
Performance zur Verfügung, welche für aufwändige Spiele reichen muss.
Da allerdings die vom Hersteller vorinstallierte Software nicht die benötigten Funktionalitäten
zur Verfügung stellt, um daraus einen Cluster zu erstellen, wird hierbei zuerst das Betriebssystem gegen eine Linux Distribution ausgetauscht. Auf der anderen Seite können Cluster
auch aus sehr vielen leistungsschwachen Knotenpcs bestehen. Dieses Konzept wurde auch bei
dem später näher beschriebenen, eigenen Versuch durchgeführt, für dem ein Cluster aus vier
Raspberrys verwendet wird. Diese Minipcs zeichnen sich durch eine geringe Größe und kleine
Stückpreise aus. Bei dem neusten, den Raspberry Zero fehlt allerdings die bei dem Vorläufern
noch vorhandene Netzwerkschnittstelle Ethernet. Diese kann durch einen USB zu Ethernet
Adapter nachgerüstet werden, soweit man auf den USB-Anschluss verzichten kann.
Cluster müssen nicht unbedingt aus gleich aufgebauten Computern bestehen, welche einen
homogenen Cluster bilden, sondern können auch aus verschieden aufgebauten Knoten bestehen. Bei den heterogenen Clustern werden Knoten mit verschiedene Hardwarekonfiguration
benützt. Diese Unterschiede können von verschieden großen Festplatten bis zu komplett verschiedenen Prozessorarchitekturen reichen[19]. Hierbei fragt sich allerdings ab einen gewissen
Punkt, ob dies sinnvoll ist, da bei zu großen Unterschieden, wie zum Beispiel dem Mischen
von ARM und X86/X64 Prozessorarchitekturen, die Software der einzelnen Knoten diesen
Unterschieden angepasst werden muss. Problematisch wird dies vor allem, wenn Software wie
beispielsweise MPI.NET mit Open MPI verwendet wird, welche für eine Architektur gar nicht
oder nur in verschieden Version erhältlich ist. Dies hat sich uns in unseren Eigenversuch gezeigt. Obwohl Open MPI und MPI.NET Open Source ist, war es uns nicht möglich diese
Software auf unsere Raspberrys zu installieren. Auch können solche Unterschiede bei der Entwicklung von Programmen wichtig sein, da z. B. nicht mehr davon ausgegangen werden darf,
dass auf jedem Knoten dasselbe Problem z. B. in derselben Zeit gelöst werden kann.
Im Nachfolgendem wird zwischen X86 und X64 nicht weiter unterschieden, da X64 hauptsächlich neben weiteren Erweiterungen, in Gegensatz zu X86, auf einer 64-Bit Architektur
aufbaut, aber weiterhin großteils kompatibel zu seinen Vorgänger ist[20].
15
4.1
Prozessor
Cluster können wie oben bereits erwähnt aus den verschiedensten Computern erstellt werden.
Das bedeutet allerdings zugleich auch, dass aus einer Vielzahl von verschiedenen Prozessoren
für die Knoten ausgewählt werden kann. So sind z. B. sechs der Top zehn Cluster in November
2015 mit Intel Xeon E5 Prozessoren ausgestattet[7], diese haben bis zu 18 Kernen und eine
Taktfrequenz von bis zu 3,5 GHz. So steht beim Planen eines Clusters die Entscheidung an,
ob besonderer Wert auf die Anzahl der Kerne oder die Leistung der Einzelnen gelegt wird. Die
Leistung der Kerne setzen sich sowohl aus der Taktzahl, den verwendeten Befehlssatz, sowie
dessen Architektur zusammen [21]. Bei Aufgaben, welche sich gut in viele kleinere skalieren
lässt, ist es oft vorteilhaft auf eine höhere Parallelität zu setzen, andernfalls ist vor allem die
Einzelkernleistung entscheiden. Auch gibt es bei einigen Programmen, die zum Ausführen von
Software auf Clustern dienen, teilweise Probleme bei der Verwaltung von mehreren Threads,
da bei dem MPI Prozess entweder mehrere Threads die MPI Aufgaben selbstständig behandeln, oder alle MPI Aufrufe von einem einzigen verwaltet werden. Im letzten Fall kann dieser
Thread zum Flaschenhals werden. Aber nicht nur im Punkt Performance, sondern auch die
Fehleranfälligkeit erhöht sich durch sehr viele Threads [22]. Dieses Problem könnte bei dem
nächsten Standard von MPI verringert werden, indem die Skalierbarkeit erhöht wird.[22, S. 78]
Von Seiten der Prozessorarchitektur herrschen zur Zeit die X86 Prozessoren im Cluster Bereich vor. Die im direkten Vergleich zu den X86 energiesparendere Lösung ARM ist allerdings
bei weitem noch nicht so leistungsfähig. Auch haben die ARM-Prozessoren den Nachteil, dass
sie die Netzwerkschnittstelle nicht so gut mit Daten versorgen können, wie ihre X86 Konkurrenz. Somit findet man in High-Performance Computing Bereich vor allen X86 Prozessoren.
Wird hingegen auf die Rechenleistung pro Watt oder pro Preis geachtet, kann ein Wechsel
zu der ARM Architektur lohnend sein, da somit die Energiekosten gesenkt werden können.
Auch soll, laut AMD, zukünftig ein Mix aus X86 und ARM Prozessoren angeboten werden.[23]
4.2
Festplatten Speicher
Für die Verwaltung der Daten auf den Speichern der einzelnen Knoten gibt es mehrere Möglichkeiten. Hierfür gibt es mehrere Konzepte, welche untereinander noch gemischt werden
können.
4.2.1
Speicherlose Knoten
Dieses Konzept findet z. B. bei den sogenannten Pegasus Clustern Anwendung. Um die Kosten
der Festplatte bei den einzelnen Knoten einzusparen, können die einzelnen auch über keine
eigenen Festplatten verfügen[25]. Das Betriebssystem sowie alle weiteren Daten werden hierbei
über das Netzwerk in den Arbeitsspeicher der einzelnen Knoten gespeichert, allerdings kann
bereits das Betriebssystem mehrere Gigabyte in Anspruch nehmen wie später in 5.1 noch erwähnt wird. Dies spielt bei Betriebssystemen mit nur kleiner Größe keine so gewichtige Rolle
mehr, da der Arbeitsspeicher in aktuellen PCs meist groß genug ist. Hierzu wird auf eine der
Seiten, welche den Aufbau dieses Konzepts vertreten geschrieben: »this is hardly an issue,
since 128 MByte out of a total RAM of 16 GByte is not really noticeable«[25].
16
Abbildung 4.1: Im Diagramm ist zu sehen, dass die Leistungsaufnahme von den ARM Prozessoren geringer ist als die der X86 Konkurrenz. Lediglich bei dem A15 trifft dies nicht zu.
Dieser ist allerdings auch auf hohe Performance ausgelegt. Je kleiner der Wert umso geringer
ist der Stromverbrauch. [24]
4.2.2
Knoten mit jeweils eigenem und geteiltem Speicher
Damit jeder Knoten auf den selben Speicherbestand zurückgreift, kann unter Linux mit Network Filesystem bzw. unter Windows mit Server Message Block ein Ordner zwischen den
Knoten geteilt werden oder die einzelnen Knoten wie bei 4.3 mit den Cluster-Speicher direkt
über die üblichen Anschlüssen verbunden werden. Hierbei ist auf der Festplatte der Knoten
jeweils das eigene Betriebssystem installiert. Neben diesem können noch weitere Daten wie
zum Beispiel zur Auslagerung aus dem RAM lokal gespeichert werden. Somit ist es für den
Administrator leichter den Cluster zu verwalten, da alle Knoten auf die selben Daten zurückgreifen. Wird nun eine Änderung an den Daten durchgeführt, ist diese für jedem Knoten im
Cluster verfügbar. Nachteilig ist allerdings, dass wenn dieser Speicher ausfällt, alle Knoten im
Cluster nicht mehr weiterarbeiten können. Somit sollte möglichst sichergestellt werden, dass
dieser Cluster-Speicher nicht ausfällt. Dies kann z. B. durch ein Redundant Array of Inexpensive Disks sichergestellt werden. Bei den HA-Cluster findet man meist diesen Aufbau, damit
bei einem Ausfall eines Knoten, ein anderer an den selben Daten weiterarbeiten kann [26].
Ein Nachteil falls der Speicher über das Netzwerk geteilt wird, ist, dass schon alleine für die
Datenverwaltung die Netzwerkverbindung belastet wird. Auch ist die Zugriffszeit auf Festplatten, die direkt mit den Knoten verbunden sind, besser. Des Weiteren kann es zu Problemen
führen, wenn mehrere Knoten gleichzeitig an ein und der selben Datei lesend bzw. schreibend
zugreifen, da es sonst unter Umständen zu Speicherinkonsistenz führen könnte. Um dies zu
vermeiden, müssen wie bei Multithreading die Zugriffe geregelt werden. Dies kann bei einen
HA-Cluster nicht auftreten, da normalerweise je ein Knoten aktiv ist und ein anderer erst
dessen Aufgaben übernimmt, wenn dieser ausfällt [26].
17
Abbildung 4.2: Im Diagramm ist zu sehen, dass die Performance von den ARM Prozessoren
geringer ist als die der X86 Konkurrenz. Je kleiner der Wert umso besser ist die Performance[24]
4.2.3
Knoten mit eigenem Speicher
Wenn es nicht nötig ist, dass jeder Knoten auf den gleichen Speicher zugreift kann jeder Knoten seinen eigenen Speicher besitzen, ohne dass dieser über das Netzwerk geteilt wird. In
vielen Clustern müssen allerdings Daten synchron gehalten werden, oder Änderungen an allen
Knoten gemacht werden, dies ist bei dieser Art der Speicherverwaltung allerdings nachteilig,
da Änderungen an allen Knoten einzeln gemacht werden müssen. Bei dem versuchsweise aufgebauten Raspberry Cluster wurde z. B. auf einen Knoten alle Konfigurationen gemacht und
dessen SD-Karte anschließend geklont. Damit das auszuführende Programm auf allen Knoten
verfügbar ist, verteilt ein Bash-Script dieses vor dem Ausführen auf alle anderen Knoten.
Diese auch als »shared-nothing« bekannte Architektur eignet sich besonders, wenn viele Lesezugriffe nötig sind. Somit findet man diesen Aufbau häufig bei "Data Warehouses". Ein
weiterer Vorteil ist, dass ein so aufgebauter Cluster leicht erweitert werden kann, da neue
Knoten nur über die Netzwerkschnittelle mit den Cluster verbunden werden müssen[27].
4.3
Netzwerk
Die »Grundvoraussetzung dafür, dass verschiedene Einzel-PCs gemeinsam ein Problem lösen
können, ist das Netzwerk, das sie verbindet und über das die PCs ihre gemeinsame Arbeit koordinieren«[28, S. 53]. Dies ist besonders wichtig wenn die Anwendung, welche auf den Cluster
läuft, einen hohen Kommunikationsaufwand zwischen den einzelnen Knoten erfordert.
18
Abbildung 4.3: HA-Cluster mit zwei Knoten, von denen einer ausgefallen ist und beide auf
den selben Speicher zugreifen.[26]
Reicht das gewählte Netzwerk nicht aus um die Übertragungszeiten klein zu halten, kann
die volle Leistung des Clusters nicht ausgenutzt werden, da die einzelnen Knoten länger auf
die Übertragung von Daten der anderen warten müssen.
Um diesen Zeitverlust möglichst gering zuhalten, kann sowohl die Netzwerk Topologie als auch
die verwendete Technologie den Bedürfnissen des Clusters entsprechend gewählt werden.
Ein weiterer Punkt der bei der Wahl des Netzwerkaufbaus betrachtet werden muss sind
die Aufwendungen, da nicht »selten die Kosten der Netzwerktechnik pro Knoten genauso hoch
wie die der gesamten restlichen Hardware eines Knotens«[28, S. 54] sind.
Wie in Abb. 4.4 erkennbar ist, ist der Aufruf von Daten aus dem Hauptspeicher im Vergleich zur Übertragung durch die Netzwerke in allen Punkten effektiver. Aus diesen Grund
kann die Leistung des Cluster verbessert werden, indem möglichst wenig Kommunikation
zwischen den einzelnen Knoten verursacht wird. Abhängig davon, ob besonders viele kleine
Datenpakete oder zumeist größere übertragen werden sollen, liegt der Fokus auf die Größe der
19
Abbildung 4.4: Eigenschaften der Netzwerktypen sowie die des Hauptspeichers [29]
Bandbreite bzw. auf eine geringe Latenzzeit.
»Diese Verzögerungen« durch die Latenzzeit »fallen dann ins Gewicht, wenn die parallelen
Anwendungen auf den verschiedenen Knoten in ständigem Kontakt miteinander sind - beispielsweise, weil sie permanent Statusinformationen austauschen müssen«[30].
Teilen sich die einzelnen Knoten die Bandbreite, wie bei Ethernet, »steht jedem Kommunikationskanal nur noch ein Bruchteil der Bandbreite zur Verfügung« [30]. Um diesen Nachteil
auszugleichen, kann man in den einzelnen Knoten mehrere Netzwerkkarten verbauen.
Bei Ethernet erzeugt vor allem der »zweimalige Weg durch die Netzwerkstacks der Betriebssysteme«[30] siehe Abb.4.5 eine höhere Latenzzeit. Dies wird bei SCI und Myrine umgangen,
indem der TCP/IP-Stack umgangen wird.
Abbildung 4.5: Rot: Nachricht mit SCI oder Myrine, Blau: Ethernet [30]
Zu der Technologie QsNet bzw. QsNet² ist zu erwähnen, dass trotz der Ankündigung und
Vorstellung der nächsten Version QsNet³ mit 25Gbit/s, was eine Verdreifachung der Bandbrei20
te in Vergleich zu der Vorversion darstellt, sich die Herstellerfirma Quadrics aus dem Geschäft
zurückgezogen hat. Dieser Schritt erfolgte, nachdem ein Teil des Kernteams die Firma verlassen hatte, um selbst eine neue Firma zu gründen[31].
Bei der hauptsächlich für HPC entwickelten Netzwerktechnologie QsNet zeigen sich auch,
die oben bereits erwähnten hohen Kosten pro Knoten, welche hierbei zwischen 1700 und 3300
US Dollar liegen.
21
Kapitel 5
Implementation
5.1
Betriebssysteme (Johannes Krafft)
»Jeder Cluster Node ist ein eigenständiger Rechner welcher, in irgend einer Weise, ein Betriebs[s]ystem braucht.«[32]
5.1.1
Windows HPC
Seit 2006 gibt es den »Windows Compute Cluster Server 2003«. Microsoft hat dafür ein eigenes MPI Protokoll names Microsoft Messaging Passing Interface definiert. [32] Ein Microsoft
Compute Cluster besteht aus einem »Head Node« und einem oder mehr »Compute Nodes«.
Der »Head Node« dient mittels eines User Interfaces als Zugriffspunkt auf das Cluster. Zur
Steuerung kann man zwischen einem GUI-Tool namens »Compute Cluster Job Manager«
oder einem Kommandozeilen-Interface wählen. [33] Geyer kritisiert, das die Nodes einen überdurchschnittlich großen Arbeitsspeicherverbrauch haben und das auf jedem »Compute Node«
unnötigerweise ein Windows Desktop läuft. [32]
5.1.2
Linux
Eine Linux Distribution erfüllt laut Geyer »alle Anforderungen die an Cluster Betriebs[s]ysteme
gestellt werden:« [32] Der Kernel ist von vornherein Netzwerkfähig, hat ein gutes Sicherheitskonzept implementiert und produziert weniger Overhead als die Konkurrenz von Microsoft.
Durch den geringeren Ressourcenverbrauch ist die notwendige Hardware für die Nodes außerdem preisgünstiger. [32]
Es besteht unter Linux natürlich immer die Möglichkeit sich selbst ein für das Rechnen im
Cluster optimiertes Betriebssystem zu konfigurieren.
Auch für diesen Zweck gibt es jedoch schon vorgefertigte Distributionen. Als Beispiel genannt
werden kann die »Rocks Cluster Distibution« basierend auf CentOS. Die Distribution wirbt
für sich mit einer besonders einfachen Installation (»From Zero to Cluster in Just Three
CDs«[34]) und vielen Erweiterungsmöglichkeiten.[34]
22
5.2
5.2.1
Message Passing Interface (Bodo Brand)
Einführung
Wenn man einen Cluster-Computer betreiben möchte, braucht man zu der entsprechenden
Hardware auch Software, die ermöglicht, auf dem Cluster-Computer ein Programm auszuführen. Wie in dem Buch »Cluster Computing, Praktische Einführung in das Hochleistungsrechnen auf Linux-Clustern«[11] beschrieben, kommunizieren die einzelnen Knoten untereinander
mit Nachrichtenaustausch. Dazu braucht der Programmierer Schnittstellen, um Daten zu senden und zu empfangen. Solche Schnittstellen wurden in dem Standard message-passing library
interface specification oder kurz MPI festgelegt [35, S. 33]. Durch den Standard wurden die
Syntax und Semantik für die Programmiersprachen C, C++ und FORTRAN bestimmt [11].
Die Implementation dieses Standards kann jedoch variieren. So stellen manche Supercomputerhersteller eigene MPI Implementationen bereit, die auf die Hardware optimiert sind [11].
5.2.2
Programmiergrundlagen mit MPICH2
Die Implementation MPICH2 wird bei dem aktuell schnellsten Supercomputer der Welt eingesetzt [36] (Rangliste November 2015). Diese Implementation ist von Argonne National Laboratory entwickelt worden und unterstützt in der Version 2 auch Infiniband, eine Hochgeschwindigkeitsübertragungstechnik, neben TCP/IP-Netzen [11, S. 120].
Um das Programmieren eines MPI Programms zu erläutern, wird im folgenden »Hello World«
in C demonstriert. Wie man in 5.1 sehen kann, wird zunächst die MPI Bibliothek mit
#include <mpi.h> eingebunden. Diese beinhaltet alle Befehle, die im MPI Standard festgelegt sind und alle mit einem »MPI_« beginnen [22, S. 60]. Nach dem Start des Programms
wird zuerst die MPI-Umgebung initialisiert. Dazu wird folgende Schnittstelle verwendet:
i n t MPI_Init ( i n t ∗ argc , c h a r ∗∗ argv )
Keine MPI-Funktion außer MPI_Initalized darf vor MPI_Init aufgerufen werden [11, S. 384].
Durch den Befehl wird ein Kommunikator zwischen allen Prozessen, die entstanden sind,
initialisiert, der im Code als MPI_COMM_WORLD erkannt werden kann. Zudem werden
alle weiteren internen Variablen erstellt, die global verfügbar sind [37]. Die Argumente dieser
Schnittstelle sind dabei nach dem MPI-2 Standard nicht mehr nötig und werden mit NULLPointern aufgefüllt. Der Kommunikator ist ein wichtiges Konzept von MPI und erlaubt die
Kommunikation zwischen allen Prozessen, die der Kommunikator umfasst. So steht standardmäßig der Kommunikator MPI_COMM_WORLD zur Verfügung, der alle Prozesse umfasst,
dieser kann jedoch aufgeteilt werden in Kommunikatoren, die weniger Prozesse umfassen [38].
Jeder Prozess bekommt durch den Kommunikator einen einzigartigen Rang (engl. rank), der
im nächsten Schritt gelesen wird. Dazu benötigen wir die nächste Schnittstelle:
i n t MPI_Comm_rank(MPI_Comm comm, i n t ∗ rank )
Der Rang, den jeder Prozess bekommt, ist eine Zahl zwischen Null und der Anzahl der Prozesse
in dem angegeben Kommunikator. Da der Rang einzigartig ist, werden somit bei 4 Prozessen
die Zahlen von Null bis Drei vergeben. Jeder Prozess hat nach diesem Schritt somit eine
andere Zahl in der Variablen world_rank stehen. Im nächsten Schritt wird ausgelesen, wie
der Hostname des Knotens heißt, auf dem der Code gerade ausgeführt wird. Dazu wird die
folgende Schnittstelle verwendet:
23
Abbildung 5.1: Hello World Beispiel mit MPI unter C [37]
i n t MPI_Get_processor_name ( c h a r ∗ name , i n t ∗ name_length )
Nun schreiben alle Prozesse in die Standardausgabe ihren Hostnamen, ihren Rang und die
Anzahl der Prozesse, die beim Starten entstanden sind. Ganz am Schluss ist noch folgende
Schnittstelle wichtig:
i n t MPI_Finalize ( )
Diese Funktion gibt alle benutzten Systemressourcen wieder frei und es dürfen keine MPIFunktionen mehr aufgerufen werden [11].
5.2.3
MPI Implementationen Vergleich
Eine beliebte weitere kostenlose Alternative zu MPICH2 ist OpenMPI. OpenMPI bietet einige
Features, wie z.B. eine Programmierschnittstelle für Java, die den aktuellsten MPI Standard
unterstützt. Ältere Implementationen wie LAM/MPI, LA/MPI und FT-MPI sind in dieses
Projekt mit eingeflossen [39].
Im Vergleich dazu wird die hochqualitative Implementierung von MPICH als Basis für neue
MPI Implementation gewählt [40]. Aus MPICH wurde z.B. die kostenpflichtige Intel MPI
Library erschaffen, welche mit höherer Performance im Vergleich zu OpenMPI wirbt [41].
Außerdem ist aus MPICH auch MVAPICH entstanden [40].
24
Kapitel 6
Anwendungsbeispiel (Bodo Brand)
6.1
Wahl der Hardwarearchitektur
Wie man in Abbildung 6.1 sehen kann, besteht unser experimenteller Cluster aus vier Raspberry Pis 2 Model B, welche über ein Switch verbunden sind.
Abbildung 6.1: Versuchsaufbau für einen experimentellen Cluster
6.2
Wahl der MPI Implementierung
Da die Funktionalitäten bei beiden Implementationen (OpenMPI und MPICH2) für unser
Projekt keinen Unterschied machen, war unser Hauptmerkmal die einfache Installation der
Implementation. Nach mehreren fehlgeschlagenen Versuchen, OpenMPI auf dem Raspberry
PI zu kompilieren, entschieden wir uns schließlich MPICH2 zu nehmen, welches via Packagemanager ohne Probleme installiert werden konnte.
25
6.3
Installation und Konfiguration
Um parallele Anwendungen auf allen 4 Raspberry Pis gleichzeitig laufen zu lassen, haben
wir auf einem Raspberry Pi MPICH2 installiert und anschließend das Image auf die anderen
Raspberries geklont. Damit die einzelnen Knotenpunkte des Clusters untereinander kommunizieren können, muss der Host, der den MPI Prozess startet, eine Secure Shell Verbindung zu
den anderen Knotenpunkten aufbauen können, ohne dass eine Passworteingabe erforderlich
ist. Dazu wird mit dem Befehl ssh-keygen -t rsa -b 2048 ein öffentlicher und privater
Schlüssel erstellt, welcher auf dem RSA Kryptographieverfahren beruht. Anschließend wird
an jeden Raspberry Pi mit dem Befehl ssh-copy-id pi@piXX der öffentliche Schlüssel übertragen. In unserem Testcluster kann nun der Raspberry Pi 01 auf die Raspberry Pis 02-04
über SSH zugreifen, ohne ein Passwort einzugeben (vgl. Abbildung 6.1). Über ein Hostfile
kann nun jeder Hostname oder jede IP-Adresse eingetragen werden, welche dann beim Start
des Programms mit angegeben werden.
6.4
6.4.1
Anwendungsfall Hashcracker
Einführung
Ein typisches Anwendungsgebiet von hoher Rechenleistung und Parallelität ist das Knacken
von Passwörtern. Da Passwörter oft als Hash in einer Datenbank gespeichert werden [42],
liegt es nahe, ein Programm zu entwerfen, welches alle möglichen Kombinationen über ein begrenztes Alphabet durchtestet und schaut, welches Wort den entsprechenden Hashwert ergibt.
Dabei verzichten wir darauf, die Möglichkeit zu geben, einen Salt und/oder Pepper an das
Passwort anzuhängen, um die Komplexität des Programms zu vermindern.
6.4.2
Umsetzung
Um den Hashcracker umzusetzen, haben wir uns zunächst überlegt, wie man den Prozess
parallelisieren kann. Die Idee, die wir zunächst dabei verwendet haben, ist ein Zusammenspiel zwischen dem Rang, den jeder Prozess bekommt und der Anzahl der Prozesse insgesamt.
Dazu ist in 6.2 der entsprechend optimierte Pseudocode zu sehen. Durch diesen Ansatz über-
Abbildung 6.2: Parallelisierungsansatz MPI Hashcracker
springt jeder Prozess die Aufgaben der anderen Prozesse. Jedoch ist dieser Ansatz nicht sehr
26
effizient, da einige Operationen wie z.B. Subtraktion und Inkrementieren wegen dem Überspringungsprozess so oft ausgeführt werden, dass man dies deutlich an der Geschwindigkeit
merkt. Um die Performance lindernden Operationen aus der Schleife herauszunehmen, benötigt man einen anderen Ansatz. Die Idee beinhaltet dabei eine Funktion, die die folgende
Schnittstelle aufweist:
i n t g e n e r a t e ( l o n g s t a r t _ i n d e x , l o n g end_index )
Man gibt dieser Funktion einen start_index , ab der wievielten Buchstabenkombination
angefangen werden soll und einen end_index , ab der wievielten Buchstabenkombination aufgehört werden soll. Somit würden mit dem Alphabet abc und dem Aufruf »generate(1,5)«
die Kombinationen: a,b,c,aa,ba durchgetestet werden und mit dem Aufruf »generate(6,8)« die
Kombinationen: ca, ab und bb. Hierbei wird zunächst anhand dem start_index die Wortlänge und der Offset zum ersten Wort der Wortlänge berechnet. Dazu kommen die folgenden
Formeln zum Einsatz:
Wortlänge = (int)(log(start_index*(anzahl_buchstaben-1))/log(anzahl_buchstaben))
Offset = start_index-((pow(anzahl_buchstaben,Wortlänge-anzahl_buchstaben)
/(anzahl_buchstaben-1))-1
Bei einem start_index von 6 ist die Wortlänge 2 mit einem Offset von 2 zu dem ersten Wort
der Wortlänge. Wenn i die Position des Buchstabens vom Wort ist, kann man nun mit der
Formel ((Offset/pow(Wortlänge,i)))%Wortlänge das Anfangswort generieren. Ab diesem
Startwort werden nun end_index - start_index viele weitere Kombinationen durchgetestet und diese geben dann zurück, ob das gesuchte Passwort dabei war oder nicht. Nun könnte
man theoretisch alle Aufgaben auf alle Prozessoren aufteilen wie in Abbildung 6.3. Die Anzahl
Abbildung 6.3: 2. Parallelisierungsansatz MPI Hashcracker
der Aufgaben ist in Abbildung 6.3 die Anzahl aller Kombinationsmöglichkeiten bis zu einer
bestimmten maximalen Wortgröße, die das Passwort haben darf. Dieser Ansatz hat jedoch
zwei Probleme. Das erste Problem ist, dass je nachdem wie viele Aufgaben, also wie viele
Kombinationen es insgesamt gibt, sich diese nicht fair auf eine bestimmte Anzahl Prozesse
aufteilen lassen. Bei diesem Ansatz könnten am Schluss durch Rundungsfehler Kombinationen weggelassen werden. Das zweite Problem ist, dass durch die Tatsache, dass es bei größeren
Wortgrößen wesentlich mehr Kombinationen gibt, die meisten Prozesse an den größten Wortgrößen arbeiten werden und extrem wenige Prozesse an den kleinen Wortgrößen. Das heißt,
wenn ich einen Hashcracker mit der maximalen Wortgröße 8 laufen lasse, dann sind 7 von 8
Prozessen mit der Wortgröße 8 beschäftigt und nur einer mit der Wortgröße 1 bis 7. Das heißt,
es findet ein Passwort relativ spät, wenn die Wortgröße kleiner als 8 ist. Aus unserer Sicht
logisch wäre es, erst die kleinen Passwörter gemeinsam durchzuprobieren und dann progressiv
27
sich in der Wortlänge zu steigern, da man dann den Fortschritt besser einschätzen kann und
schon nach kurzem weiß, ob das Passwort bei den kleineren Wortlängen dabei ist oder es sich
eventuell gar nicht mehr lohnt weiterzusuchen, da bereits eine bestimmte Wortlänge erreicht
ist, die einen zu großen zeitlichen Aufwand benötigen würde. Um beide Probleme zu lösen, haben wir schließlich eine passende Lösung entwickelt, welche man in Abbildung 6.4 sehen kann.
Die Variable Alphabet ist dabei die Anzahl der Buchstaben im vorgegebenen Alphabet, von
Abbildung 6.4: Finaler Parallelisierungsansatz MPI Hashcracker
dem alle Kombinationen durchgetestet werden sollen. Wie man in Abbildung 6.4 sehen kann,
wird zunächst die Anzahl aller Kombinationen berechnet und in anzahl_aufgaben gespeichert. Daraufhin wird eine sinnvolle Paketgröße festgelegt. Wenn es genug Prozesse gibt, dass
alle Kombinationen aufgeteilt werden können, ohne dass einer zu viele bekommen würde, dann
wird die entsprechende Paketgröße mit len_dictionary/world_size berechnet, andernfalls
ist eine maximale Paketgröße gesetzt, welche bevorzugt genommen wird, wenn die Pakete zu
groß werden würden. Die maximale Paketgröße kann von System zu System variieren und umso größer man diese wählt, umso länger braucht ein Prozess das Paket abzuarbeiten. Das if in
Zeile 10 von Abbildung 6.4 sorgt dafür, dass, wenn der letzte Prozess über die maximale Aufgabenanzahl geht, der end_index entsprechend angepasst wird, um eine Punktlandung auf
die maximale Aufgabenanzahl zu schaffen. Wenn ein Prozess die Antwort gefunden hat, ruft
er am Schluss MPI_Abort(MPI_COMM_WORLD, 0) auf, um alle anderen Prozesse anzuhalten.
28
Kapitel 7
Geschwindigkeit (Bodo Brand)
Um die Geschwindigkeit des Hashcrackers zu testen, ließen wir alle Passwörter über dem Alphabet a-z bis zur Länge 5 durchtesten und haben dann die Anzahl Passwörter pro Sekunde
berechnet aus alle Kombinationen/gebrauchte Zeit . Es gibt 12.356.630 mögliche Kombinationen und diese werden in Pakete geteilt und an die einzelnen Prozesse verteilt. Da die Zeit
erst gestoppt wird, wenn der letzte Prozess fertig ist, ist es wichtig die Paketgröße so zu wählen, dass die Aufgaben fair verteilt werden. Wenn beispielsweise die Paketgröße 1.000.000 wäre
und 8 Prozesse die Aufgabe bearbeiten sollen, dann müssen vier Prozesse 1.000.000 Kombinationen mehr machen als drei der anderen Prozesse. Der achte Prozess müsste 356.630 mehr
Kombinationen durchtesten. Das würde das Ergebnis verfälschen. Somit haben wir die Paketgröße auf 50.000 festgelegt, damit der Mehraufwand einiger Prozesse keine Rolle mehr spielt.
Zudem ist die Anzahl Prozesse ein entscheidendes Kriterium für die Geschwindigkeit, da die
CPU optimal ausgelastet werden sollte, um die höchste Geschwindigkeit zu erreichen. Deshalb wurden die Tests auf einer Zweierpotenz an Prozessen durchgeführt, damit die Prozesse
sich optimal auf die verschiedenen Raspberry Pis verteilen können. Wenn beispielsweise acht
Prozesse auf vier Raspberries ausführen möchte, dann werden automatisch zwei Prozesse pro
Raspberry ausgeführt. Eine Faustregel für die Festlegung der Anzahl Prozesse pro Host ist,
dass man einen Prozess pro CPU Kern ausführt, jedoch gibt es auch »hyperthreaded cores«,
welche mehr als einen Prozess pro Kern gleichzeitig abfertigen können [43]. So wird, wie in
Abbildung 7.1: Geschwindigkeitsvergleich
Abbildung 7.1 zu sehen, bei einem Mac Book Pro Mid 2014 ein höherer Durchsatz an Passwörtern pro Sekunde gemessen, wenn man vier Prozesse statt zwei Prozesse benutzt, obwohl
der Prozessor zwei physikalische Kerne hat. Die MPICH2 FAQ Seite[44] empfiehlt, nicht mehr
29
Prozesse zu nehmen als CPU Kerne, da es sonst zu hohen Performanceverlusten kommen
kann. Dieses Verhalten kann man hauptsächlich an allen vier Raspberry Pis und dem Intel
Core i7 feststellen. Einflüsse, die nicht beachtet wurden, sind die Betriebssystemauslastung,
RAM-Geschindigkeit und weitere Einflüsse, die hier einen Unterschied machen können.
30
Kapitel 8
Zusammenfassung und Ausblick
(Bodo Brand)
8.1
Erreichte Ergebnisse
Durch unseren Versuchsaufbau konnten wir zeigen, wie man in der Praxis einen Cluster Computer umsetzen kann. Auch wenn ein Raspberry Pi 2 nicht unbedingt für einen Cluster geeignet
ist und uns viele Probleme bereitet hat, konnten wir dennoch eine MPI Software entwickeln,
welche die Probleme der parallelen Programmierung aufzeigt. Problemstellungen zu parallelisieren, wie z.B. das Cracken eines Hashcodes, zeigt auch wie komplex ein Problem werden
kann, dass für einen einzelnen Rechner wesentlich einfacher zu entwickeln gewesen wäre.
8.2
Ausblick
Die Anzahl der Cluster Computer ist groß und wird schätzungsweise noch lange als Mittel
benutzt, um hohe Performance und hohe Ausfallsicherheit zu erreichen. Jedoch kann sich das
auch schnell ändern, so ist die Forschung in Quantencomputern gerade im vollem Gange,
welche in Zukunft höhere Rechenleistung versprechen als aktuelle Supercomputer und somit
selber zu Supercomputern werden. Wenn auch diese Aussage momentan noch mit Vorsicht zu
genießen ist, da viele Problemstellungen nur schwierig umzusetzen sind, damit das Konzept
vom Quantencomputer ausgenutzt werden kann. Da Passwörter heutzutage eher mit GPU geknackt werden, ist der Hashcracker auf den Raspberry Pis nicht unbedingt sinnvoll. Dennoch
zeigt es die Arbeitsweise eines Cluster Computers und bringt mit 16 Cores bereits eine unerwartet hohe Rechenleistung mit. So können Privatpersonen sich ein Cluster bauen, welches mit
einem Minimum an Preis eine hohe Rechenleistung bietet. Mit immer neueren Generationen
von Raspberry Pis werden diese sogar noch leistungsstärker oder noch billiger, wie man am
Raspberry Pi Zero sehen kann.
31
Literatur
[1]
(). Zwei neue hochleistungsrechner bringen rheinland-pfalz im wissenschaftlichen rechnen
an die forschungsspitze, Adresse: https : / / www . uni - mainz . de / presse / 52192 . php
(besucht am 10. 06. 2016).
[2]
(). Cluster noun - definition, pictures, pronunciation and usage notes | oxford advanced learner’s dictionary at OxfordLearnersDictionaries.com, Adresse: http : / / www .
oxfordlearnersdictionaries . com / definition / english / cluster _ 1 ? q = cluster
(besucht am 26. 05. 2016).
[3]
(). What is computer cluster? - definition from techopedia, Techopedia.com, Adresse:
https://www.techopedia.com/definition/6581/computer- cluster (besucht am
21. 05. 2016).
[4]
(). What is the difference between cloud, grid and cluster? - stack overflow, Adresse: http : / / stackoverflow . com / questions / 9723040 / what - is - the - difference between-cloud-grid-and-cluster (besucht am 28. 05. 2016).
[5]
D. Christl, M. Riedel und M. Zelend. (). Kommunikationssysteme / rechnernetze, Adresse: http://marcus.zelend.de/studium/clustertools/clustertools.pdf (besucht
am 04. 06. 2016).
[6]
C. Meyer. (). What is the difference between a supercomputer and a computer cluster?
- quora, Adresse: https://www.quora.com/What- is- the- difference- between- asupercomputer-and-a-computer-cluster (besucht am 26. 05. 2016).
[7]
(). List statistics | TOP500 supercomputer sites, Adresse: http://www.top500.org/
statistics/list/ (besucht am 26. 05. 2016).
[8]
(). What is the different between a cluster and MPP supercomputer architecture - stack
overflow, Adresse: http://stackoverflow.com/questions/5570936/what- is- thedifferent - between - a - cluster - and - mpp - supercomputer - architecture (besucht
am 27. 05. 2016).
[9]
R. Büst. (2010). Was ist grid computing? : Clouduser, Adresse: https://clouduser.
de/grundlagen/was-ist-grid-computing-156 (besucht am 28. 05. 2016).
[10]
D. Fey, D. Bender und B. Klauer, Hrsg., Grid-Computing: Eine Basistechnologie für
Computational Science, Ser. eXamen.presLink hinter Ïn: In diesem Buch, Zeitschriftenoder Konferenzband befindet sich der Aufsatz!, Berlin: Springer, 2010, 523 S., isbn:
978-3-540-79746-3 978-3-540-79747-0.
32
[11]
H. Bauke und S. Mertens, Cluster Computing: Praktische Einführung in das Hochleistungsrechnen auf Linux-Clustern. Berlin; New York: Springer, 2006, OCLC: 63137601,
isbn: 978-3-540-29928-8. Adresse: http://public.eblib.com/choice/publicfullrecord.
aspx?p=323280 (besucht am 26. 05. 2016).
[12]
M. Armbrust, A. Fox, R. Griffith, A. D. Joseph, R. H. Katz, A. Konwinski, G. Lee, D. A.
Patterson, A. Rabkin, I. Stoica und M. Zaharia, »Above the clouds: A berkeley view of
cloud computing«, EECS Department, University of California, Berkeley, UCB/EECS2009-28, Feb. 2009. Adresse: http://www.eecs.berkeley.edu/Pubs/TechRpts/2009/
EECS-2009-28.html.
[13]
(). Cluster computing -hweidner.de, Adresse: http://www.hweidner.de/docs/Cluster_
Computing/ (besucht am 07. 06. 2016).
[14]
(). Failover cluster, Microsoft Developer Network, Adresse: https://msdn.microsoft.
com/de-de/library/ff650328.aspx (besucht am 04. 06. 2016).
[15]
(). Load-balanced cluster, Microsoft developer network, Adresse: https://msdn.microsoft.
com/de-de/library/ff648960.aspx (besucht am 04. 06. 2016).
[16]
(). What is supercomputer? webopedia definition, Adresse: http://www.webopedia.
com/TERM/S/supercomputer.html (besucht am 06. 06. 2016).
[17]
(). HITACHI SR2201 massively parallel processor, Adresse: http://www.hitachi.co.
jp/Prod/comp/hpc/eng/sr1.html (besucht am 06. 06. 2016).
[18]
G. B.J, C. B und F. P. J. (). Building a large low-cost computer cluster with unmodified xboxes, Adresse: http://www.bgfax.com/school/xbox/Xbox_ICPADS2004.pdf
(besucht am 07. 06. 2016).
[19]
h. online heise. (). Der heterogene supercomputer, heise online, Adresse: http://www.
heise.de/newsticker/meldung/Der- heterogene- Supercomputer- 83095.html (besucht am 11. 06. 2016).
[20]
(). Was ist x64 und x86? wo ist der unterschied?, Adresse: http://www.softwareok.
de/?seite=faq-System-Allgemein&faq=13 (besucht am 11. 06. 2016).
[21]
(). Server und HPC-cluster schon mit neuer haswell-plattform | virtua, Adresse: http:
//www.virtual-reality-magazin.de/server-und-hpc-cluster-schon-mit-neuerhaswell-plattform (besucht am 08. 06. 2016).
[22]
J. Schüle, Paralleles Rechnen: Performancebetrachtungen zu Gleichungslösern. Oldenbourg Verlag, 1. Jan. 2010, 237 S., isbn: 978-3-486-71158-5.
[23]
F. Riemenschneider. (). AMDs server-prozessoren zukünftig auch mit ARM, elektroniknet.de, Adresse: http://www.elektroniknet.de/halbleiter/prozessoren/artikel/
92437/ (besucht am 09. 06. 2016).
[24]
(). Page 2 - the final ISA showdown: Is ARM, x86, or MIPS intrinsically more power
efficient? | ExtremeTech, Adresse: http://www.extremetech.com/extreme/188396the - final - isa - showdown - is - arm - x86 - or - mips - intrinsically - more - power efficient/2 (besucht am 09. 06. 2016).
[25]
(). How to build a diskless cluster?, Adresse: http://web.mst.edu/~vojtat/pegasus/
administration.htm (besucht am 05. 06. 2016).
33
[26]
(). Schrittweise anleitung für failovercluster: Konfigurieren eines dateiserver-failoverclusters
mit zwei knoten, Adresse: https : / / technet . microsoft . com / de - de / library /
cc731844(v=ws.10).aspx (besucht am 08. 06. 2016).
[27]
(). Architectures for clustering: Shared nothing and shared disk, Adresse: http://www.
mullinsconsulting.com/db2arch-sd-sn.html (besucht am 09. 06. 2016).
[28]
L. L. Chowdhry. (2005). Cluster computing - CodeProject, Adresse: http : / / www .
codeproject.com/Articles/11709/Cluster-Computing (besucht am 21. 05. 2016).
[29]
G. Bengel, C. Baun, M. Kunze und K.-U. Stucky, Masterkurs Parallele und Verteilte
Systeme: Grundlagen und Programmierung von Multicore-Prozessoren, Multiprozessoren, Cluster, Grid und Cloud. Springer-Verlag, 20. Mai 2015, 504 S., isbn: 978-3-83482151-5.
[30]
D. O. Diedrich. (). Preiswerte hochleistungsrechner mit clustern, c’t, Adresse: http :
//www.heise.de/ct/artikel/Einigkeit- macht- stark- 287954.html (besucht am
05. 06. 2016).
[31]
Marvyn. (6. Juli 2009). Insidetrack: Former employees confirm quadrics officially out of
business last week, insideHPC, Adresse: http://insidehpc.com/2009/07/insidetrackfromer-employees-confirm-quadrics-officially-out-of-business-last-week/
(besucht am 05. 06. 2016).
[32]
R. Geyer, »Linux cluster in theorie und praxis«, TU Dresden, 19. Okt. 2009, Adresse:
https://tu- dresden.de/die_tu_dresden/zentrale_einrichtungen/zih/lehre/
ws0910/lctp_stuff/K3_Betriebssysteme.pdf (besucht am 04. 06. 2016).
[33]
(). Introduction to microsoft windows compute cluster server 2003, Adresse: https :
//technet.microsoft.com/en-us/library/cc720163(v=ws.10).aspx (besucht am
04. 06. 2016).
[34]
(). Www.rocksclusters.org | rocks website, Adresse: http://www.rocksclusters.org/
wordpress/ (besucht am 07. 06. 2016).
[35]
(2015). Mpi: A message-passing interface standard version 3.1, Adresse: http://www.
mpi-forum.org/docs/mpi-3.1/mpi31-report.pdf (besucht am 16. 05. 2016).
[36]
(). Tianhe-2 (MilkyWay-2) - TH-IVB-FEP cluster, intel xeon e5-2692 12c 2.200ghz, TH
express-2, intel xeon phi 31s1p | TOP500 supercomputer sites, Adresse: http://www.
top500.org/system/177999 (besucht am 26. 05. 2016).
[37]
(). MPI hello world · MPI tutorial, Adresse: http://mpitutorial.com/tutorials/mpihello-world/ (besucht am 30. 05. 2016).
[38]
nptelhrd. (). Mod-09 lec-40 MPI programming, Adresse: https://www.youtube.com/
watch?v=mzfVimVbguQ (besucht am 10. 06. 2016).
[39]
(). Differences between LAM MPI and OpenMPI - stack overflow, Adresse: http://
stackoverflow . com / questions / 8770005 / differences - between - lam - mpi - and openmpi (besucht am 05. 06. 2016).
[40]
(). Mpi - MPICH vs OpenMPI - stack overflow, Adresse: http://stackoverflow.com/
questions/2427399/mpich-vs-openmpi (besucht am 05. 06. 2016).
[41]
(). Intel® MPI library | intel® software, Adresse: https://software.intel.com/enus/intel-mpi-library (besucht am 10. 06. 2016).
34
[42]
(). Security - best way to store password in database - stack overflow, Adresse: http:
/ / stackoverflow . com / questions / 1054022 / best - way - to - store - password - in database (besucht am 03. 06. 2016).
[43]
(). MPICH2 examples on biowulf, Adresse: https : / / hpc . nih . gov / docs / mpich2 _
examples.html (besucht am 11. 06. 2016).
[44]
(). Frequently asked questions - mpich, Adresse: https://wiki.mpich.org/mpich/
index.php/Frequently_Asked_Questions (besucht am 11. 06. 2016).
35