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
© Copyright 2024 ExpyDoc