Leopold–Franzens–Universität Innsbruck Workflow Simulation

Werbung
Leopold–Franzens–Universität
Innsbruck
Institut für Informatik
Forschungsgruppe DPS
(Distributed and Parallel Systems)
Workflow Simulation Execution
Bachelorarbeit
Betreuer: Kassian Plankensteiner
Felix Koenig (0917104)
[email protected]
Innsbruck
22. Mai 2012
Zusammenfassung
Workflow Execution Simulation ist eine Arbeit, welche die Simulation von
Workflows auf Grids realisiert. Es sollen Workflows in Form von gerichteten
azyklischen Graphen erstellt werden können und mittels diversen Scheduling
Verfahren auf die Ressourcen verteilt werden. Zudem muss eine Ausführung
des Workflows simuliert werden. Die Algorithmen und deren Implementierung
sind in der Thesis aus theoretischer und praktischer Sicht beschrieben. Das
Programm verwendet die Funktionalität zur Erstellung von Grids und der
Ausführung von Jobs die von dem Simulator GroudSim bereitgestellt wird.
Inhaltsverzeichnis
1 Einführung
1.1 Definition von Grids und Clouds . . . . . . . . . . . . . . . . . .
1.2 Problem und Motivation . . . . . . . . . . . . . . . . . . . . . . .
1.2.1 Fehlerverhalten und erneutes Senden von Jobs . . . . . .
1
1
2
3
2 Theoretische Grundlagen
4
2.1 Verwendete Workflows . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1 Wien2k . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.2 Povray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.3 Balanced-Graph . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.4 Leveled-Graph-With-Preselected-Maximum-Link-Complexity
(LDPMC) . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.5 LU-Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Heterogeneous-Earliest-Finish-Time-Algorithmus(HEFT) . . . . . 7
2.2.1 Das Scheduling-Problem . . . . . . . . . . . . . . . . . . . 7
2.2.2 Priorisierungsphase . . . . . . . . . . . . . . . . . . . . . . 8
2.2.3 Zuordnungsphase zu den Prozessoren . . . . . . . . . . . . 8
2.3 Fehlertoleranz und Fehlerreaktion . . . . . . . . . . . . . . . . . . 9
2.4 HEFT-Replication-Algorithmus . . . . . . . . . . . . . . . . . . . 10
2.5 Replicate All . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.6 Resubmission-Impact Verfahren . . . . . . . . . . . . . . . . . . . 10
2.6.1 Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.7 Dynamic-Enactment Strategie . . . . . . . . . . . . . . . . . . . . 11
2.7.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.7.2 Der Algorithmus . . . . . . . . . . . . . . . . . . . . . . . 12
2.7.3 RI-Rescheduling . . . . . . . . . . . . . . . . . . . . . . . 13
3 Implementierung
3.1 Ziele des Simulators und Programmeingabeinformationen . . .
3.2 Verwendung und Konzepte von GroudSim . . . . . . . . . . . .
3.3 Programmaufbau . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.1 Workflow Generator . . . . . . . . . . . . . . . . . . . .
3.4 Scheduling-Komponente . . . . . . . . . . . . . . . . . . . . . .
3.4.1 HEFT-Implementierung . . . . . . . . . . . . . . . . . .
3.4.2 HEFT-Replication-Implementierung ohne erneutes Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4.3 Resubmission-Impact Implementierung . . . . . . . . . .
3.4.4 Parallelisierung von Resubmission-Impact . . . . . . . .
3.5 Die Ausführungskomponente . . . . . . . . . . . . . . . . . . .
iv
.
.
.
.
.
.
15
15
15
17
17
22
22
.
.
.
.
24
24
25
26
3.5.1
3.5.2
3.5.3
Schnittstelle zu GroudSim . . . . . . . . . . . . . . . . . . 27
Implementierung des Enactment Verfahrens . . . . . . . . 27
Weitere Eingabedateien anhand von Beispielen erklärt . . 29
4 Experimente
4.1 Performancetest . . . . . . . . . . . . . . . . .
4.2 Kosten- und Laufzeitenvergleich verschiedener
4.2.1 Erfolgsrate . . . . . . . . . . . . . . .
4.2.2 Laufzeitenvergleich . . . . . . . . . . .
4.2.3 Kostenvergleich . . . . . . . . . . . . .
5 Zusammenfassung
. . . . . . . . .
Fehlerszenarien
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
.
.
.
.
.
.
.
.
.
.
31
31
32
32
33
34
39
1 Einführung
In den heutigen Anwendungsgebieten von Rechenmaschinen spielen Grids und
Clouds eine wesentliche Rolle. Es gibt diverse Bereiche in der Wirtschaft und
Forschung, bei welchen viel Rechenleistung verlangt wird und große Mengen
an Daten verarbeitet werden müssen. Es kann dann durchaus von Nöten sein,
diverse Grid- oder Cloudsysteme anzumieten um den Mangel an benötigten
Rechenressourcen auszugleichen und auszubauen. Da die Anmietung solcher
Systeme Geld kostet, wird man sich bemühen seine Ressourcen möglichst effizient zu nützen.
Es geht somit um folgende Fragestellungen. ”Wie viele Ressourcen benötigt
man mindestens um eine vorgegebene Gesamtlaufzeit einzuhalten?” und ”Wie
wirken sich Systemfehler in den Ressourcen auf die Laufzeit aus?”.
1.1 Definition von Grids und Clouds
Im obigen Teil wurden Grids und Clouds als mögliche Ressourcen angegeben.
Als Grid bezeichnet man ein System welches drei Eigenschaften besitzt die im
Folgenden beschrieben werden.[1]. Die erste Eigenschaft bezieht sich auf die
koordination von Ressourcen, wie zum Beispiel Massenspeicher, Datenbanken,
Anwendungen oder Rechner. Diese Ressourcen können von diversen Benutzern
angesprochen werden. Eine Ressource wäre in dieser Arbeit eine Grid Site, welche Prozessoren zur Ausführung verschiedener Programme anbietet. Im Kapitel
über GroudSim sind diese Ressourcen genauer beschrieben. Ein Grid bietet zudem als zweite Eigenschaft Schnittstellen an, die der Authorisierung und dem
Ressourcenzugriff dienen. Ein Grid koordiniert seine eigenen Ressourcen in einer Art und Weise, welche den Erwartungen des Benutzers gerecht werden soll.
Dem Benutzer sollen Dienstgüte bereitgestellt werden, dies ist die dritte Eigenschaft von Grids. Es können neue Ressourcen kombiniert werden, um zum
Beispiel die Gesamtleistung des Systems zu steigern. Beim Grid-Computing
geht es hauptsächlich darum, einen virtuellen Hochleistungsrechner, welcher
eigentlich aus mehreren gekoppelten Rechnern besteht, zu erzeugen. Weitere
Informationen zu Grids findet man in [2]. Das Prinzip von Grids ist, dass sich
mehrere Nutzer und Organisationen die Ressourcen teilen. Bei Clouds geht es
darum, dass jeder Nutzer auch individuell Ressourcen anmieten kann. Zudem
gibt es hier mehrere Varianten. Clouds können Firmenintern angelegt sein, dabei handelt es sich um private Clouds. Sie können öffentlich zugänglich sein,
wie zum Beispiel der Cloud Service von Amazon. Daneben gibt es hybride Varianten, die beide Konzepte vereinen und Community-Clouds. Letzere bietet
für Gemeinschaften und Mitglieder breiterer Organisationen, wie zum Beispiel
Personen innerhalb einer Universität, Rechenresourcen an. Weitere Informatio-
1
1 Einführung
nen zu Cloud Systemen findet man in [3] und [4]. Eine ausführlichere Definition
von Cloud Computing, findet man in [5].
1.2 Problem und Motivation
Es seien n Ressourcen gegeben die Grids bzw. Clouds repräsentieren. Diesen
Rechenmaschinen sollen nun k Jobs zugeteilt werden. Ein Job stellt meistens
ein Programm, oder einen Arbeitsablauf dar welcher viel Rechenleistung und
Zeit benötigt. Zwischen den Jobs bestehen sehr wohl Abhängigkeiten. Es ist
somit möglich, dass das Ergebnis von Job A für Job B von Nöten ist. Man kann
eine einfache geschachtelte Rechenoperation zu Rate ziehen. Wenn man den
Term (5 · 2) + 10 betrachtet, wird man zum Schluss kommen, dass die Bekanntgabe des Ergebnisses nur dann erfolgen kann, wenn zuerst der Subterm (5 · 2)
ausgewertet wird. Man könnte in unserem Fall die Operation (5 · 2) als Job A
bezeichnen. Job B bildet die Operation x + 10 ab, wobei x das Ergebnis von
Job A darstellt. Abstrakt gesehen bilden Job A und Job B einen gerichteten
Graphen mit zwei Knoten.
In der Praxis wird man viele Jobs mit vielen Abhängigkeiten vorfinden, weshalb
sich ein großer Graph bildet. Diesen Graph bezeichnen wir in diesem Projekt
als Workflow. Die Knoten werden in dieser Arbeit als solche identifiziert oder
Jobs genannt.
Die Ressourcen besitzen jeweils eine unterschiedliche Rechenleistung, die Jobs
eine unterschiedliche Problemgröße. Das Problem besteht nun darin, den Graphen effizient auf die vorhandenen Ressourcen zu verteilen und möglichst optimale Start- und Endzeitpunkte für die Ausführung der jeweiligen Jobs zu
definieren. Mit dem Kriterium ”optimal” wird hier das Ziel angesprochen, die
Gesamtlaufzeit für alle Jobs zu minimieren. Betrachtet man die Zuteilung der
2
1.2 Problem und Motivation
Jobs an die jeweiligen Ressourcen, also den Schedule der Jobs, ensteht wieder
ein Graph welcher vom ursprünglichen Workflow abhängig ist. In diesem Graphen gibt es einen kritischen Pfad, dieser gibt in Summe die längste Laufzeit
vor. Konkret gilt es diese Zeit zu minimieren.
1.2.1 Fehlerverhalten und erneutes Senden von Jobs
Das Scheduling Problem kann mithilfe eines Algorithmus gelöst werden. Es ergibt sich jedoch noch ein weiteres Problem. Sind einige Ressourcen fehleranfällig,
muss man aufgrund eines Systemfehlers Jobs teilweise abbrechen, um sie anschließend neu auszuführen. Somit wird die vorhergehende Berechnung der
Start- und Endzeitpunkte der jeweiligen Jobs invalidiert, da sich das gesamte Szenario verzögert. Bei vielen Fehlern können teilweise große Abweichungen
zum ursprünglichen Schedule entstehen. Die reale Fertigstellungszeit des Workflows wird sich von der zuvor berechneten stark unterscheiden. In vielen Fällen
ist es nun nötig, das Scheduling anzupassen und neu zu errechnen. Um ein
solches Verhalten zu testen benötigt man nun einen Simulator, welcher diese
Szenarien simuliert und uns Auskunft über die benötigte Gesamtlaufzeit und
den damit verbundenen Kosten liefert. Ziel dieser Arbeit ist es nun einen solchen
Simulator zu realisieren.
3
2 Theoretische Grundlagen
Um einen Simulator zu realisieren welcher dieses Workflow-Scheduling Problem löst und auf Fehlerverhalten in den Ressourcen reagiert, benötigt man
diverse Algorithmen und Verfahren. Der Algorithmus welcher auf das Verteilungsproblem von Jobs auf Ressourcen eingeht und in dieser Simulation implementiert ist, trägt den Namen HEFT (Heterogeneous-Earliest-Finish-TimeAlgorithm). Des Weiteren sollte der Simulator Fehlerszenarien realisieren. Anschließend müssen Verfahren angewendet werden, welche die Auswirkungen der
Fehler möglichst gering halten. Wenn häufig Fehler auftreten und fast immer die
gleichen Jobs davon betroffen sind, so wird man sich überlegen, ob man nicht
mehrere Kopien dieser Jobs auf verschiedene Ressourcen auslagert, anstatt diese Jobs andauernd wieder an die gleiche Ressource zu schicken. Eine wichtige
Rolle bei dieser Überlegung spielt ebenfalls die benötigte Dauer der einzelnen
Jobs. Benötigt ein Job viel Rechenleistung und dauert er sehr lange, so werden vermutlich mehrere Kopien von ihm erzeugt, da ein erneutes Ausführen
des Jobs auf der Ressource vermutlich mehr Zeit beanspruchen würde. Das
Resubmission-Impact Verfahren in Kombination mit HEFT-Replication, bietet
hier einen möglichen Lösungsweg. Abschließend benötigt man ein Verfahren,
welches den Gesamtablauf simuliert und die Algorithmen korrekt verwendet.
Dieses Verfahren trägt den Namen Dynamic-Enactment und bildet den Kern
der Simulation. Im Folgenden werden die einzelnen Algorithmen detailiert erklärt. Der Simulator unterstützt nur eine begrentzte Anzahl an Workflows. Die
Eigenschaften und Beschaffenheit dieser Graphen wird auf den folgenden Seiten
ebenfalls erörtert.
2.1 Verwendete Workflows
Die Workflows welche in diesem Projekt verwendet werden sind allesamt gerichtete azyklische Graphen. Die Knoten stellen hierbei Jobs, dar. Gibt es eine
Kante zwischen einem Job X zu einem Job Y, so muss der Job X zuerst abgearbeitet werden. Eventuell wird ein Datentransfer von X nach Y getätigt
bevor man Y ausführen kann. Ein Knoten besitzt eine bestimmte Anzahl an
Instruktionen, welche von den Ressourcen abgearbeitet werden müssen um den
Job erfolgreich zu beenden. Diese Zahl wird auch die Problemgröße genannt.
Die Kanten des Graphen können mit einem Wert gewichtet sein welcher die zu
transferierende Datenmenge darstellt. Die Anzahl an Instruktionen pro Knoten
ist vom Typus des Workflows abhängig. Auf das Verfahren zur Bestimmung der
Instruktionsanzahl wird beim Kapitel über die Implementierung eingegangen.
Für die Realisierung der Algorithmen, muss jeder Workflow jeweils aus einem
ausgezeichneten Wurzel- und Endknoten bestehen. Ist dies nicht der Fall, so
wird der fehlende Knoten mit einer minimalen Problemgröße hinzugefügt.
4
2.1 Verwendete Workflows
2.1.1 Wien2k
Der Wien2k Workflow setzt sich aus einzelnen Iterationen zusammen. Eine Iteration besteht aus fünf Ebenen, einem Wurzelknoten n1, n Nachfolgeknoten,
einem gemeinsamen Nachfolger n6 auf welchen wieder n Folgeknoten fallen. In
der letzten Ebene befindet sich wieder ein einzelner Nachfolgeknoten n11. Es
können i Iterationen aneinandergereiht werden, wodurch sich ein Workflow der
Höhe i · 5 ergibt. Die Anzahl an Instruktionen für die n Knoten in der Ersten
Ebene ist meistens um den Faktor 10 größer als jene für die n Knoten in der
dritten Ebene.
Abbildung 2.1: Ein Beispiel eines Wien2k-Graphen [6]
2.1.2 Povray
Dieser Workflowtypus besteht lediglich aus 3 Ebenen. In der zweiten Ebene
befinden sich n Knoten welche allesamt einen gemeinsamen Nachfolger n9 besitzen. Um den Graphen für Algorithmen zu standardisieren wird noch ein Wurzelknoten n1 vor den n Knoten in der ersten Ebene angehängt. Standardmäßig
besteht der Povray Graph nur aus Ebene 2 und 3. Die Anzahl an Instruktionen
von n9 hängt von der Anzahl und Problemgröße der Vorgänger ab.
Abbildung 2.2: Ein Beispiel eines Povray-Graphen [6]
2.1.3 Balanced-Graph
Dieser Graph ist dem Wien2k-Workflow sehr ähnlich. Er besteht aus einem
Wurzelknoten und aus k Ebenen welche aus jeweils n Knoten bestehen und
5
2 Theoretische Grundlagen
einen Block bilden. Die n Knoten innerhalb des Blockes haben wieder n Nachfolger, wobei jeweils ein Knoten genau einen Nachfolger besitzt. Die Knoten
in der letzten der k Ebenen besitzen wieder einen gemeinsamen Nachfolger.
Es kann in einem Balanced Graphen mehrere Blöcke geben, die jeweils durch
einen gemeinsamen Vorgänger- beziehungsweise Nachfolgeknoten voneinander
getrennt sind.
Abbildung 2.3: Ein Beispiel eines Balanced-Graphen [6]
2.1.4 Leveled-Graph-With-Preselected-Maximum-Link-Complexity
(LDPMC)
Dieser Graph besitzt eine Anzahl an Ebenen k, in jeder Ebene gibt es bis
zu n Knoten. Ab der zweiten Ebene bestimmt ein Wert l wieviele Vorgänger
ein Knoten in der Ebene maximal besitzen darf. Die Auswahl und Anzahl der
Vorgänger erfolgt jeweils durch Zufall wobei ein Vorgänger eines Knotens v
maximal eine Ebene über v liegen darf. Es wird abschließend noch ein letzter
Knoten in den Graphen eingefügt um ihn für Algorithmen zu standardisieren.
Abbildung 2.4: Ein Beispiel eines LDPMC-Graphen [6]
6
2.2 Heterogeneous-Earliest-Finish-Time-Algorithmus(HEFT)
2.1.5 LU-Graph
Bei diesem Workflow bestimmt ein einziger Faktor, nämlich die Anzahl k an
Ebenen das Aussehen des gesamten Graphen. Die Höhe k ist dabei immer eine
gerade Zahl. Betrachtet man den Graphen vom Endknoten zum Wurzelknoten
so stellt man fest, dass sich die Anzahl an parallelen Knoten in jeder Ebene mit
einer geraden Zahl um 1 erhöht.
Abbildung 2.5: Ein Beispiel eines LU-Graphen [6]
2.2 Heterogeneous-Earliest-Finish-TimeAlgorithmus(HEFT)
2.2.1 Das Scheduling-Problem
Der HEFT-Algorithmus bietet eine mögliche Lösung für eine effiziente Zuordnung der Jobs an die Ressourcen. Konkret ist ein Workflow W = (V, E) mit V
Knoten gegeben, wobei V die Menge an v Knoten bezeichnet und E die Menge
an e Kanten. Der Knoten welcher keine Vorgänger besitzt wird als entry job
bezeichnet, derjenige welche keine Nachfolger besitzt wird exit job genannt.
In dieser Arbeit beschäftigen wir uns nur mit Grids als möglichen Ressourcen.
Jeder Grid beinhaltet mehrere Prozessoren, insgesamt sind q Prozessoren aus
einer Menge p Q verfügbar. Die Leistung der Prozessoren ist von Grid zu
Grid verschieden. Die Knoten sollen nun unter Einhaltung der Abhängigkeiten
zwischeneinander und unter minimierung der Ausführungszeit, den jeweiligen
Prozessoren zugewiesen werden. Dieses Problem ist NP-Hart, um eine effiziente Implementierung ermöglichen zu können, wendet man hier ein heuristisches
Verfahren, welches eine gute Lösung bietet, an. Der HEFT-Algorithmus ist der
Klasse der List-Scheduling-Algorithmen zuzuordnen. Der Algorithmus wird in
2 Phasen eingeteilt. Phase 1 dient der Priorisierung der Jobs, Phase 2 dient der
Zuordnung der Jobs an die einzelnen Prozessoren. Die generellen Schritte des
Algorithmus sind:
7
2 Theoretische Grundlagen
1
2
3
4
5
6
7
8
Bilde Mittelwerte für die Laufzeiten von der Jobs und Kanten auf allen Ressourcen
Berechne den Rank für alle Jobs, beginnend mit dem letzten
Sortiere die Jobs nach den Ranks in absteigender Reihenfolge in einer Liste l
solange es unzugeordnete Jobs gibt:
Wähle den ersten Job n von l
für jeden Prozessor p mache folgendes:
Berechne den Fertigstellungszeitpunkt für n auf p EFT(n,p)
Ordne Job n demjenigen Prozessor zu welcher den EFT-Wert minimiert
2.2.2 Priorisierungsphase
Diese Phase bezieht sich auf die ersten drei Schritte im Algorithmus. Zunächst
wird ein Mittelwert wmi für die Ausführungsdauer des jeweiligen Jobs ni gebildet. Dabei stellt W eine v × q Matrix dar, in welcher die Kosten wi,j für ni auf
dem jeweiligen Prozessor pi eingetragen sind. Der Mittelwert wmi ergibt sich
durch:
q
X
wmi =
wi,j /q[7]
j=1
Zusätzlich zu wmi bildet man noch ein Mittelwert cmi,k über die Datentransferzeiten von Job ni zu Job nk . In diesem Projekt spielen diese Zeiten allerdings
keine Rolle und sind mit einem Standardwert initialisiert.
Anschließend geht es zu Schritt 2, der Berechnung des Wertes ranku für jeden
Knoten. Ziel ist es, eine Liste an Knoten zu erstellen welche Schritt für Schritt
den Ressourcen zugeordnet werden können. Hier kommt diesem Wert eine große
Bedeutung hinzu. Der ranku bildet sich aus der Formel:
ranku (ni ) = wmi +
max
(cmi,j + ranku (nj ))[7]
nj succ(ni )
succ(ni ) ist die Menge an direkten Nachfolgern von ni . Der ranku errechnet
sich aus einer Rekursion, beginnend mit dem Endknoten nlast des jeweiligen
Graphen. Für nlast gilt somit folgende Rekursionsabbruchbedingung:
ranku (nlast ) = wmlast [7]
Nun werden die Knoten anhand des jeweiligen ranku , in absteigender Reihenfolge sortiert. Dies hat zur Folge, dass sich nun der Graph in Form einer Liste
abzeichnet. Die jeweiligen Abhängigkeiten zwischen den Jobs bleiben bestehen.
So befindet sich ein Job ni mit einem kleineren Index wie Job nj auch im Graphen auf mindestens der gleichen Ebene wie Job nj . Falls sich ni und nj im
Workflow auf derselben Ebene befinden, so wird zufällig bestimmt ob ni einen
kleineren Index in der Liste besitzt oder nicht.
2.2.3 Zuordnungsphase zu den Prozessoren
In dieser Phase werden die Jobs schlussendlich den jeweiligen Prozessoren zugeteilt. Das entscheidende Kriterium für eine solche Zuteilung ist der EF T -Wert,
8
2.3 Fehlertoleranz und Fehlerreaktion
dieser bezeichnet das frühestmögliche Abarbeitungsende des Jobs. Er wird aus
dem EST -Wert, dem frühestmöglichen Startzeitpunkt berechnet.
EST (ni , pj ) = max pavailable[j], max (AF T (nm ) + cm,i ) [7]
nm pred(ni )
Der Startzeitpunkt für den Knoten ni auf dem Prozessor pj ergibt sich somit
aus dem Maximum der fix zugeordneten Endzeiten AF T aller Vorgänger nm
und deren Transferzeiten cm,i zu ni . Zusätzlich muss noch in Betracht gezogen werden, ob der Prozessor pj zum Startzeitpunkt und für die Dauer der
Ausführung von nj verfügbar ist. Diese Zeit wird durch pavailable[j] dargestellt. Das wichtige ist hierbei, einen freien Zeitpunkt zu finden, in dem die
Zeitspanne groß genug ist um den Knoten ni ausführen zu können. Der Beginn
des frühestmöglichen, freien Zeitschlitzes, auf welchen dieses Kriterium zutrifft
wird in pavailable[j] gespeichert. Das hat zur Folge, dass neue Knoten auch
zwischen 2 bereits zugeteilten Knoten, unter Beibehaltung der Präzedenzen,
eingefügt werden können. Der EF T -Wert ergibt sich nun folgendermaßen:
EF T (ni , pj ) = wi,j + EST (ni , pj )[7]
Der Endgültige Wert für die Endzeit AF T ergibt sich nun aus dem minimum
aller EF T -Werte.
AF T (ni ) = min (EF T (ni , pj )) [7]
pj Q
Der Knoten wird somit dem Prozessor pj zugeteilt. Folglich errechnet sich der
AST -Wert, also der endgültige Startzeitpunkt durch folgende Formel:
AST (ni ) = AF T (ni ) − wi,j [7]
2.3 Fehlertoleranz und Fehlerreaktion
In diversen Szenarien muss mit fehleranfälligen Ressourcen gearbeitet werden.
Häufig führt ein Ausfall eines Grids oder eines Prozessors zum Abbruch mehrerer Jobs. Die Frage ist nun, wie man auf solche Fehler reagieren kann, ohne dass
sich die tatsächliche Laufzeit des Workflows stark von der Ursprunglichen unterscheidet. Im Allgemeinen gibt es 2 mögliche Lösungsansätze. Es können bereits
im Vorhinein Replikate pro Job angefertigt werden. Sind genügend Ressourcen
zur Verfügung, kann man die Replikate ebenfalls effizient auf die Ressourcen
verteilen, ohne die Gesamtlaufzeit wesentlich zu verzögern. Dabei tolerieren r
Replikas einen maximalen Ausfall von r Prozessoren. Der Vorteil ist, dass die
Gesamtlaufzeit minimal verzögert wird. Der Nachteil besteht allerdings in einer
höheren Ressourcennutzung. Die andere Variante würde zur Ausführungszeit
des Workflows zum Einsatz kommen. Sobald ein Job fehlschlägt wird er nochmals an dieselbe Ressource gesendet, hierbei kann man ebenfalls ein Maximum
von s erneuten Versuchen definieren. Der Vorteil dieser Variante ist, dass nicht
mehr Ressourcen als ursprünglich vorgesehen benötigt werden. Der Nachteil
besteht in einer teils großen Verzögerung der Gesamtlaufzeit. Ziel ist es nun
beide Verfahren zu verwenden und dabei ein gutes Mittelmaß zwischen r und
s zu finden. Die zuständigen Algorithmen zur Lösung dieses Problems lauten
HEFT-Replication und Resubmission-Impact.
9
2 Theoretische Grundlagen
2.4 HEFT-Replication-Algorithmus
Das HEFT-Replication Verfahren, behandelt die effiziente Zuteilung der Knoten und ihrer Replikas an die Ressourcen, mithilfe des HEFT-Algorithmus. Der
zusätzliche Parameter in diesem Algorithmus ist der Vektor RV , welcher die
vorgesehene Anzahl an Replikas ri pro Knoten ni V beinhaltet.
Die Phasen des Algorithmus sind analog zu denen des HEFT-Verfahrens. Zunächst
wird der ranku für jeden Knoten ni ermittelt, anschließend sortiert der Algorithmus die Knoten in einer Liste. Daraufhin erfolgt die Ressourcenzuteilung
der Jobs, mittels Berechnung von AF T und AST . Hier gibt es allerdings einen
entscheidenden Unterschied zu HEFT. Teilt man einen Knoten ni einer Ressource pi zu, so werden seine Vorgänger vi pred(ni ) überprüft. Der Algorithmus
ermittelt ob jeder Nachfolger vsuccj succ(vi ) von vi bereits einer Ressource
zugeordnet ist. Trifft dies zu, so werden ri RV Replikas von vi erzeugt. HEFT
Replication ordnet sie dann, aufgrund der AF T -Berechnung wie sie HEFT vorgibt, den Ressourcen zu. Diese Strategie hat zur Folge, dass Replikas erst dann
erzeugt und den Ressourcen zugeteilt werden, wenn alle Nachfolger bereits an
eine Ressource gebunden sind. Dadurch ist es unwahrscheinlich, dass ein Replika einem Nicht-Replika eine schnelle Ressource entwendet. Betrachtet man das
Ergebnis dieses Scheduling-Verfahrens als strikte Zuordnung, so entstehen allerdings auch offensichtliche Probleme. Schlägt die Abarbeitung eines Jobs fehl,
so muss man sich auf seine Replikas verlassen, diese starten allerdings später als
seine direkten Nachfolger, somit sind die Präzedenzen nicht mehr gewährleistet.
Dieses Problem wird aber bei der Dynamic-Enactment Strategie noch einmal
aufgegriffen und umgangen.
Es bleibt allerdings noch eine Frage offen, nämlich die Ermittlung von ri . In
meinem Simulator existieren 2 Varianten wie man diesen Wert berechnen kann.
Diese Varianten werden nun vorgestellt.
2.5 Replicate All
Diese Heuristik ist im Prinzip recht simpel. Sie beschäftigt sich mit der Berechnung von ri für jeden Knoten. Dabei wird der Funktion replicateAll einfach ein
Parameter resmax übergeben. Replicate All konstruiert nun einen Vektor RV in
dem pro ni die Werte ri gespeichert sind. Dabei wird ri mit repmax initialisiert.
Nun erfolgt der Aufruf von HEFT-Replication mit RV .
2.6 Resubmission-Impact Verfahren
Die Replicate-All Heuristik ist in diversen Fällen etwas unzureichend. Es werden zwar alle Knoten repliziert, allerdings ist die Anzahl an Replikas sehr hoch.
Es entstehen somit 2 Nachteile. Zum Einen ist die Ressourcenbelegung ziemlich
groß, zum Anderen kann es dadurch zu einer Beeinträchtigung der Gesamtausführungszeit des Workflows kommen. Dieser negative Effekt stellt sich vor
allem dann ein, wenn wenige Ressourcen vorhanden sind. Wie oben beschrieben
benötigt man oft ein ausgleichendes Verfahren. Dieses nennt sich Resubmission-
10
2.7 Dynamic-Enactment Strategie
Impact (kurz RI). Es ist nicht sinnvoll von jedem Knoten Replikas zu erstellen,
da ein etwaiges erneutes Senden von diversen Knoten oft nur wenig Auswirkungen auf die Gesamtlaufzeit hat. Ziel ist es nun, solche Jobs zu finden und die
Anzahl an ri für jene Jobs klein zu halten, im Gegensatz zu Jobs bei welchen
sich ein erneutes Senden stärker auf die Gesamtlaufzeit auswirken würde.
2.6.1 Algorithmus
Die Parameter für den Algorithmus sind der Workflow W mit den Knoten V ,
die Ressourcen Q und die Werte resmax und repmax . Die beiden letzteren beschreiben jeweils die Maximale Anzahl an erneuten Sendungen eines Jobs und
das Maximum an Replikas.
Zu Beginn wird der HEFT Algorithmus mit dem Workflow W und den Ressourcen Q aufgerufen. Das Ergebnis speichert Resubmission Impact in einer Variablen namens hef t. Es werden nun der Reihe nach alle ni V abgearbeitet. Bei
jedem Knoten ist die Anzahl an Instruktionen in einer Variable instructionsi
gespeichert. Nun berechnet man den Aufwand, um einen Knoten mit der in
resmax definierten Anzahl an Wiederholungen zu senden und speichert diesen
in der Variable instructions0i .
instructions0i = instructionsi · resmax [8]
Anschließend wird für jeden Knoten ni der HEFT-Algorithmus aufgerufen, jeweils mit der neuen Anzahl an Instruktionen, instructions0i . Die Gesamtlaufzeit
wird jeweils in der Variablen hef ti gespeichert. Nun errechnet der Algorithmus
die Differenz di , der beiden Gesamtlaufzeiten di = hef ti − hef t. Der Wert von
hef t muss nicht jedes mal neu berechnet werden, da er sich nie verändert. Je
höher di ist, umso stärker beeinträchtigt ein erneutes Senden dieses Knotens die
Gesamtlaufzeit. Nun wird für jeden Knoten ni ein normierter Wert berechnet,
welcher die Gewichtung von di im Vergleich zu allen anderen nj beschreibt. Diesen speichert der Algorithmus in einer Variablen RIi , wobei der Wertebereich
jeweils zwischen 0 und 1 liegt.
RIi = di / max(dj )[8]
Daraus errechnet man dann den tatsächlichen ri -Wert.
ri = bRIi · repmax c[8]
Statt f loor könnte man hier ebenfalls ceil verwenden. Bevor man HEFT-Replication
startet, werden die einzelnen ri wieder in dem Vektor RV gespeichert.
2.7 Dynamic-Enactment Strategie
2.7.1 Allgemeines
Das RI-Scheduling Verfahren schafft einen guten Ausgleich zwischen der Anzahl an Replikas und den erneuten Sendevorgängen. Allerdings basieren die
11
2 Theoretische Grundlagen
Verfahren alle auf demselben Schema. Die Zuteilung der Ressourcen erfolgt jeweils bevor man den Workflow schlussendlich abarbeitet. Während der Laufzeit
kommt den Algorithmen noch keine Funktionalität hinzu. Treten allerdings ungewöhnlich viele Fehler während dieser Zeit auf, so wird die Ausführungszeit des
Workflows stark von der Ursprünglichen, durch HEFT oder HEFT-Replication
berechneten, abweichen. Die Jobs werden dann vorwiegend erneut an die Ressourcen gesendet, da die Abarbeitung ihrer Replikas bereits fehlgeschlagen ist.
Hier sollte man steuernd eingreifen, etwa durch ein erneutes Auslösen und Anpassen des Scheduling Algorithmus.
Das Dynamic-Enactment Verfahren bemüht sich diesen Risikofaktor auszugleichen. Zudem wird dem User eine realistische Gesamtlaufzeit, eine sogenannte
Soft-Deadline errechnet.
2.7.2 Der Algorithmus
Im Prinzip ist das Dynamic-Enactment eine Erweiterung des RI Verfahrens.
Die Übergabeparameter sind die gleichen, jedoch wird das Enactment um zwei
Werte erweitert. Hierbei spezifiziert cmax die maximale Anzahl an Rescheduling Aktionen. Der zweite Parameter fr ist ein Faktor, welcher vor allem bei der
Berechnung der Soft Deadline zu tragen kommt. Dieser Wert gibt einen Prozentsatz an, wie weit die reale Ausführungszeit von der im Scheduling berechneten
abweichen darf, bevor ein erneuter Aufruf des Scheduling-Algorithmus getätigt
wird.
Zunächst ruft Dynamic-Enactment den HEFT-Replication Algorithmus auf um
ein initiales Schedule zu berechnen. Die Gesamtlaufzeit des Schedule wird in
der Variablen tW f gespeichert, der Zähler c welcher die Anzahl an Reschedules protokolliert, wird auf 1 gesetzt. Anschließend folgt die Ermittlung der Soft
(c)
Deadline td , nachdem ein Schwellwert tr für das Überschreiten der Laufzeit
des Workflows bestimmt ist.
t(c)
r = tW f · fr [8]
td = tW f ·
1 + fr ·
cX
max
!
(1/k) [8]
k=1
Um die oben angeführten Berechnungen verstehen zu können, sollte man die
weiteren Prinzipien des Algorithmus verstanden haben, weshalb ich erst zum
Schluss darauf eingehen werde. Im Folgenden werden nun alle ni V ermittelt,
welche bereit sind an ihre Ressource gesendet zu werden. Dabei handelt es sich
um Knoten, deren Vorgänger allesamt abgearbeitet worden sind, oder um jene
ni welche keine Vorgänger besitzen. Diese Jobs sendet man dann an die jeweilige
Ressource für deren Abarbeitung. Sobald ein Job komplett ausgeführt worden
ist, wird seine benötigte Laufzeit treal
ni mit der maximal erlaubten tni Verglichen.
Ist die Abweichung zu groß, muss ein Rescheduling stattfinden. Die Bedingung
dafür lautet folgendermaßen:
(c)
max 0, treal
ni − tni > tr ∧ c < cmax [8]
12
2.7 Dynamic-Enactment Strategie
Ist sie erfüllt, so bereitet der Algorithmus die Jobs für das Rescheduling vor.
Dabei werden nur jene ni für eine Menge N Set ausgewählt, die der Algorithmus noch nicht abgearbeitet hat. Die Daten, deren Übertragung noch ausstehen
werden ebenfalls berücksichtigt und in der Menge DSet gespeichert. Nun wendet der Algorithmus ein spezielles Verfahren namens RI-Rescheduling an, mit
N Set und DSet als Übergabeparametern, welches die verbleibenden Jobs wieder möglichst effizient auf die Ressourcen verteilt. Die Variable c wird um 1
(c)
erhöht und tr wird neu berechnet.
t(c)
r
= tW f · fr ·
cX
max
(1/k)[8]
k=1
Abschließend wird noch getestet ob der Workflow fertig abgearbeitet ist.
Beispiel für den Start des Reschedulings
(c)
Um die Berechnungen von tr und td zu Verstehen soll nun ein kleines Beispiel
(c)
eingeführt werden. Konkret soll sich tr nach jedem Rescheduling dem Wert
td - tW f mit immer enger werdenden Abständen nähern und dabei die Zeit,
um welche sich die Ausführung des Workflows verzögert hat, representieren.
Beginnt man mit tW f = 1000, fr = 0.2 und cmax = 4 so ergeben sich für
(1)
(c)
tr = 200 und für td = 1407. Der Wert von tr nähert sich schrittweise dem
von 407, der maximalen Verzögerung welche garantiert dass eine Gesamtlaufzeit
(2)
(3)
von 1407 beibehalten wird. Die konkreten Werte wären somit tr = 300, tr =
(4)
366, tr = 407. Zu beachten ist hier, dass sich der Workflow nach dem ersten
Rescheduling um mindestens 200 verzögert hat, sonst würde kein Rescheduling
erfolgen, siehe Gleichung oben. Bei c-fachem Rescheduling hat sich der Workflow
(c)
somit mindestens um den Faktor tr verzögert. Dies ist der Grund warum
(c)
(c
)
man, je näher tr , dem Wert von tr max rückt, in immer kürzer werdenden
Intervallen ein Rescheduling durchführt damit die Soft Deadline von tW f +
(c
)
tr max eingehalten wird.
2.7.3 RI-Rescheduling
Vom vorhergehenden Kapitel ist bekannt, dass dieser Algorithmus aufgerufen
wird wenn erkannt worden ist, dass sich die Ausführungszeit des Workflows
bereits ungünstig verzögert hat. Die Übergabeparameter sind der Workflow W
mit den im Dynamic-Enactment Verfahren berechneten Jobs N Set und den
Daten DSet, den Ressourcen Q, repmax und c. Dieses Verfahren hat zum Ziel,
dem bereits entstandenen Trend zur Verzögerung des Workflows entgegen zu
wirken. Dies soll dadurch erfolgen, dass man die Anzahl an Replikas von den
verbleibenden Knoten jeweils erhöht. Somit sollen Zeitverzögernde, erneute Sendungen von Jobs vermieden werden. Um dies zu erreichen, wird repi für jeden
verbleibenden Job neu berechnet.
p
repi = b c RIi · repmax c[8]
13
2 Theoretische Grundlagen
√
Durch c RIi wird RIi um den Faktor c erhöht, da sich RIi zwischen 0 und
1 befindet. Dies hat zur Folge, dass sich auch repi für ni erhöht. Somit kann
man später auch Replikas für Knoten mit einem niedrigen initialen RI bilden.
Anschließend wird RV wieder mit den neuen Werten von ri initialisiert und das
HEFT-Replication Verfahren aufgerufen.
14
3 Implementierung
Der Simulator ist in Java 1.6 implementiert. Dabei wurde das bereits existierende Programm GroudSim verwendet, welches mehrere Studenten in diversen
Bachelorprojekten entwickelt haben.
3.1 Ziele des Simulators und
Programmeingabeinformationen
Der Simulator besteht genau genommen aus zwei Teilen. Der erste Teil wird
als Workflow Generator bezeichnet und ist für die Erzeugung des Graphen verantwortlich. Die Anzahl der unterstützten Graphen in diesem Generator beschränkt sich auf jene, welche in den theoretischen Grundlagen besprochen
worden sind. Man kann allerdings problemlos weitere Graphgeneratoren hinzufügen die andere Workflows erzeugen, solange man die Schnittstellen korrekt
implementiert. Bei der Generierung des Workflows wird ebenfalls die Problemgröße (in Anzahl an Instruktionen gemessen) für jeden Knoten beziehungsweise
Job berechnet. Der zweite Teil des Simulators besteht aus den Scheduling Algorithmen und dem Dynamic Enactment. Es müssen Graphen erzeugt, effizient
mittels den Algorithmen auf Ressourcen verteilt, und anschließend mithilfe des
Enactment Verfahrens ausgeführt werden können. Das Programm verwendet
drei Dateien, diese gibt der Benutzer als Parameter beim Start der Ausführung
an. Die erste Datei beinhaltet Informationen über die Erstellung der Workflows und deren Beschaffenheit im CSV Format. Je nach Graphtypus gibt es
unterschiedliche Parameter mit verschiedenen Funktionsweisen, die bei der Erzeugung eine große Rolle spielen. Die zweite Datei, ebenfalls im CSV Format,
ist für die Erstellung der Grids relevant. Im Programm werden nur Grids als
mögliche Ressourcen verwendet. In dieser Datei werden somit die Anzahl an
Grids, deren Leistungsstärke und Fehlerverhalten angegeben. Die dritte Datei
beinhaltet Konfigurationen in Form von Schlüssel-Werte Paaren, welche den
programminternen Ablauf steuern. Als Beispiel kann die Anzahl an maximalen
Rescheduling Operationen angegeben werden, oder ein Wert welcher bestimmt
ob das Programm Fehlerverhalten realisieren soll.
3.2 Verwendung und Konzepte von GroudSim
Um einen Simulator zu realisieren, der auf diversen Ressourcen arbeitet, braucht
es ein System welches solche Ressourcen erzeugen und verwalten kann. Der Simulator GroudSim ist in der Lage Ressourcen in Form von Grids und Clouds
zu simulieren. Dieses hier beschriebene Programm verwendet die Funktionalität
des Simulators, weshalb es wichtig ist kurz den Zusammenhang zwischen beiden
15
3 Implementierung
Arbeiten zu erwähnen. Wichtig ist hier die Erzeugung von Grids, welche in meinem Simulator die Ressourcen repräsentieren. In GroudSim kann man Objekte
vom Typ GridSite erstellen, wobei jede GridSite eine bestimmte Anzahl an
Prozessoren mit einer entsprechenden Rechenleistung, die in der Abarbeitung
von Millionen Instruktionen pro Sekunde angegeben wird, besitzt. Zudem kann
man der GridSite einen Fehlergenerator zuweisen um die Dauer des Fehlers,
die Anzahl an Prozessoren und die Zeit bis zum nächsten Fehler zu bestimmen.
Eine Instanz der Klasse GridSite kann lediglich abzuarbeitende Jobs entgegennehmen und in einer Warteschlange für die zukünftige Ausführung speichern.
Die Jobs werden aus der Klasse GroudJob gebildet. Sobald eine CPU nicht mehr
von einem Job besetzt ist, weist die GridSite dem Prozessor den nächsten Job
zu, insofern die Warteschlange nicht leer ist.
Zuerst wird ein GridUser angelegt, welcher bestimmte GridSite Instanzen erstellen und Jobs an den Simulator schicken kann. Ist der User im System registriert, wird mittels Ereignissklassen kommuniziert. GroudSim generiert Informationen, wie das erfolgreiche Senden eines Jobs an einen Prozessor, die
Fertigstellung der Jobs und die Fehlschläge bei der Abarbeitung. Diese Informationen werden sofort nach dem Auftreten in Events verpackt, wobei die aktuelle Simulationszeit ebenfalls mitprotokolliert wird. Beim Dynamic-Enactment
Verfahren wird dann auf diese Ereignisse entsprechend reagiert. Die entscheidenden Klassen sind hier das JobSubmittedEventType, wenn ein Job an eine
GridSite gesendet worden ist, das JobQueuedEventType, wenn sich ein Job in
der Abarbeitungsschlange der GridSite befindet, das JobActivatedEventType,
wenn ein Job aktiviert worden ist und das JobFailedEventType, wenn ein Job
fehlschlägt. Um GroudJob Instanzen während der Ausführung in GroudSim zu
beenden, erstellt man ein JobCancelEventType und übergibt es GroudSim. Ein
Objekt vom Typ JobCancelDoneEventType signalisiert das erfolgreiche Beenden eines Jobs. Bei der Abarbeitung des jeweiligen Ereignisses ruft der Simulator die Implementierung der zugehörigen Methode im Objekt von GridUser auf.
Der GridUser leitet das Ereignis weiter, indem er Methoden in der Fassadenklasse aufruft. Schlussendlich wird die Klasse, welche das Enactment Verfahren
implementiert durch die Fassadenklasse benachrichtigt.
16
3.3 Programmaufbau
3.3 Programmaufbau
Der Aufbau des Programms lässt sich generell in drei Komponenten einteilen,
welche aufeinander angewiesen sind.
Abbildung 3.1: Die Komponenten
Den Workflow Generator, die Scheduling Komponente, mitsamt den Algorithmen für die Verteilung der Jobs auf die Ressourcen und den eigentlichen Simulator, die Ausführungskomponente. Letztere ist für das Enactment und die
Simulation des Workflows unter Zuhilfenahme von GroudSim zuständig.
3.3.1 Workflow Generator
In dieser Komponente finden sich Klassen für die Erstellung der unterstützten
Workflows. Die Erzeugung des jeweiligen Workflows wurde mithilfe der Fabrikmethode realisiert. Es gibt eine Schnittstelle namens GraphGenerator, von welcher die konkreten Workflowgeneratoren erben. Die Schnittstelle definiert eine
Methode namens public DAG generateDAG(), mit der die Graphenerstellung
erfolgt. Eine Klasse GraphGeneratorFactory liefert den entsprechenden Generator, basierend auf den eingelesenen Informationen über den Typ des Graphen,
zurück. Die Methode generateDAG() wird von der Klasse FileInputHandler
aufgerufen. Dieselbe Klasse liest die graphspezifischen Informationen von der
CSV Datei aus. Die Datei wird von InputTypeParser auf Korrektheit überprüft
bevor sie dem FileInputHandler übergeben wird. Als Ergebnis wird eine Liste
mit Workflows zurückgegeben.
Der Workflow selbst, ist in der Klasse DAG abgebildet. Hier befinden sich Referenzen auf Wurzel- und Endknoten. Knoten werden mithilfe der Klasse GraphNode
abgebildet, zwischen ihnen befinden sich Kanten welche die Klasse GraphEdge
definiert. Ein Objekt vom Typ GraphNode beinhaltet alle wichtigen Informationen, wie Referenzen auf Replikas, Nachfolge- und Vorgängerknoten, die Anzahl
an Ausführungen in GroudSim und die Problemgröße. . . .
17
3 Implementierung
Graphspezifische Informationen in der Eingabedatei
Um zu verstehen wie ein Graph erzeugt werden kann, muss man seine Beschaffenheit analysieren. Aufgrund der Struktur des Workflowtyps kann man dann
diverse Parameter bestimmten und eine passende Eingabedatei dafür konstruieren. Bei jedem Workflow müssen der exakte Name, Werte für resmax und
repmax und ein String angegeben werden, der entscheidet welchen Scheduling
Algorithmus das Enactment Verfahren verwendet. Dieser muss entweder HEFT,
RI oder ReplicateAll lauten. Diese Werte gibt der Aufrufende jeweils am Ende
der CSV Datei an. Ein weiterer wichtiger Punkt ist nicht nur die Generierung
des Workflows, sondern auch die gleichzeitige Bestimmung der Problemgöße
p eines jeden Knotens. Dabei hängen die spezifischen Grapheigenschaften eng
mit der Ermittlung der Problemgröße zusammen. Es werden pro Graph jeweils
2 Parameter α und β vom Typ Double angegeben, mithilfe derer eine Klasse ProblemSizeGenerator die Anzahl an Instruktionen pro Knoten berechnet.
Dabei ist α ein Faktor, welcher die Problemgröße des jeweiligen Knoten entweder vergrößert oder verkleinert. In der Property Datei kann man die vordefinierte Anzahl an Instruktionen instr vom Typ Double, mit welcher α multipliziert
wird, definieren. Es sollte aber nicht jeder Knoten dieselbe Problemgröße haben,
weswegen der Wert von β entscheidend ist. Der Parameter, der zwischen 0 und
1 liegen muss, gibt das Verhältnis der Problemgröße zwischen einzelnen Knoten
einer Ebene und parallelen Knoten auf einer anderen Ebene an. Konkret ergibt
sich
p = α · instr · β
für Einzelknoten und
p = α · instr · (1 − β)
falls der Knoten mehrere Nachbarn in einer Ebene besitzt. Bei den Graphen
Povray und LDPMC werden Dummyknoten angefügt. Diese Knoten haben eine
spezifische, in der Property Datei vordefinierte Größe. Die beschriebene Art der
Kostenberechnung ist ein Standard, der allerdings nicht für jeden Graphtypus
gleich ist. Im Folgenden sind die graphspezifischen Informationen für die Eingabedatei beschrieben. Zur Veranschaulichung sind pro Graph Beispielgrafiken
angegeben. Diese sollen das Ergebnis der Problemgrößenberechnung darstellen.
Wien2k Die Beschaffenheit des Wien2k Graphen lässt variable Dimensionen
bezüglich der Anzahl an Iterationen i und der parallelen Knoten pnodes in
den Ebenen 2 und 4 jeder Iteration zu. Die ersten beiden Parameter, welche
für die Konstruktion eines solchen Graphen zuständig sind, bestimmen somit
die Werte für i und pnodes. Zur Berechnung der Instruktionsanzahl einzelner
Knoten müssen zusätzlich vier Werte angegeben werden. Zwei Gewichtungen
e2, e4 sowie α und β. Liegt der Knoten in der zweiten Ebene, so ergibt sich die
Problemgröße p durch:
p = α · instr · e2 · (1 − β)
Die Anzahl an Instruktionen in der dritten Ebene einer Iteration wird durch:
p = α · instr · e4 · (1 − β)
18
3.3 Programmaufbau
berechnet. Die Idee dahinter ist, dass die Ebenen bezüglich ihrer Problemgröße
unterschiedlich stark gewichtet werden können. Meist benötigt man beim Wien2k Graph ein Verhältnis von 10 : 1 zwischen e2 und e4. Die Berechnung der
Kosten für alleinstehende Knoten einer Ebene verändert sich nicht.
Abbildung 3.2: Wien2k mit instr = 100, α = 2.0, e2 = 10, e4 = 1, β = 0.8
In jeder Ebene des Graphen sind links von den Knoten die jeweiligen Problemgrößen angegeben die sich jeweils für alle Knoten der Ebene ergeben.
Povray Zur Generierung wird hier, neben den Standardparametern ein Integer
pnodes angegeben. Dieser bestimmt die Anzahl an Knoten in der zweiten Ebene.
Die Berechnung der Problemgröße für die parallelen Knoten ergibt sich durch:
p = α · instr
Die Ermittlung der Instruktionsanzahl für den letzten Knoten erfolgt mithilfe
von pnodes und α. Dadurch wächst p für diesen Knoten je mehr Vorgänger er
besitzt. Zusätzlich wird das Ergebnis um den Faktor 0.8 etwas gedämpft.
p = pnodes · α · 0.8 · instr
Abbildung 3.3: Povray mit instr = 100, α = 2.0, β = 0.8, pnodes = 4
19
3 Implementierung
Diese Grafik zeigt die Problemgröße, die sich aus den jeweiligen Werten für
instr, α und β pro Knoten ergibt. Die Werte gelten für jeweils für alle Knoten
in der zugehörigen Ebene.
Balanced Der Erste Parameter, welcher nach dem Namen folgt, bestimmt hier
die Gesamtanzahl t an Knoten. Die tatsächlich erzeugte Knotenzahl kann allerdings variieren und hängt von den weiteren Werten ab. Der zweite Parameter
bestimmt die Anzahl an Ebenen k in einem Block mit parallelen Knoten. Die
Anzahl an Blöcken b mit k Ebenen errechnet sich durch den nächsten Parameter, der Zahl der Knoten zwischen den Blöcken a. Somit ist b = a − 1, da zwischen jedem Block ein einzelner gemeinsamer Nachfolgeknoten liegt. Die Zahl
an Nachbarknoten l in einer der b · k Ebenen ergibt sich durch l = (t − a)/(b · k).
Die Errechnung der Problemgröße jedes Knotens wird Standardmäßig mit den
Werten α und β durchgeführt.
Abbildung 3.4: Balanced Graph mit instr = 100, α = 2.0, β = 0.8
Die Problemgrößen gelten für alle Knoten in der Ebene in der sie angegeben
sind.
LU Dem GraphGenerator für diesen Workflow übergibt man zur Konstruktion nur die Anzahl an Ebenen k. Falls k ungerade ist, so wird der Wert um
1 dekrementiert. Der GraphGenerator erzeugt den Workflow beginnend beim
letzten Knoten, aufsteigend, in Richtung der Wurzel. Jede Ebene besitzt einen
Index ei welcher die Höhe darstellt. Ist ei gerade, so generiert der Algorithmus
eine Ebene mit parallelen Knoten. Die Zahl der parallelen Knoten ist jeweils
um 1 größer als in der Ebene ei − 2. Ist ei ungerade, so wird nur ein einzelner
Knoten erstellt. Die Kostenberechnung erfolgt nach dem Standardverfahren.
20
3.3 Programmaufbau
Abbildung 3.5: LU Graph mit instr = 100, α = 2.0, β = 0.8
LDPMC Der erste Parameter nach dem Namen bestimmt die Gesamtanzahl
t an Knoten ohne den Wurzelknoten. Der zweite Parameter bestimmt die Gesamtanzahl der Ebenen k. Somit ergibt sich die Größe pnodes der Knoten pro
Ebene durch pnodes = t/k. Ab der zweiten Ebene wird per Pseudozufall bestimmt wieviele Vorgänger ein Knoten besitzt und um welche Knoten von der
Ebene zuvor es sich dabei handelt. Die maximale Anzahl an Vorgängern spezifiziert dabei der dritte Parameter. Dieser Wert muss allerdings größer als 1
sein, da die minimale Anzahl an Vorgängern 1 ist. Um die Simulation mit den
gleichen Zufallszahlen noch einmal ausführen zu können, muss ein spezieller
Wert vom Typ Long dem Zufallsgenerator übergeben werden. Diese Zahl wird
durch den vierten Parameter bestimmt. Die Anzahl an Instruktionen für den
Wurzelknoten ergibt sich aus dem Standardverfahren, für die Ermittlung der
Problemgröße pro Knoten in den weiteren Ebenen wird allerdings die Anzahl
der Vorgänger predecessors des jeweiligen Knoten in Betracht gezogen. Somit
ergibt sich für jeden Knoten in den Ebenen nach dem Wurzelknoten folgende
Formel für p:
p = α · instr · predecessors · (1 − β)
Abbildung 3.6: LDPMC-Ausschnitt mit instr = 100, α = 2.0, β = 0.8
21
3 Implementierung
Die in der Grafik dargestellten Werte neben den Knoten gelten jeweils nur für
die Grün gefärbten Knoten und nicht pro Ebene.
Beispiel für die Eingabedatei zur Workflow Generierung
Als Beispiel ist der Inhalt einer CSV-Datei angegeben, aus der ein Wien2k
Graph erzeugt werden kann.
1
Wien2k; 5; 4; 10; 1; 1.0; 0.65; 4; 4; RI;
Der Erste Parameter stellt den korrekten Namen des Workflows dar damit
der zugehörige Generator aufgerufen werden kann. In diesem Beispiel wird der
Graph mit 5 Iterationen, welche jeweils 4 parallele Knoten in den Ebenen e2
und e4 der Iteration i besitzen, initialisiert. Dies spezifizieren die Werte 5 und 4
nach dem Namen. Die weiteren 2 Parameter geben das Verhältnis der Problemgröße zwischen den Knoten in e2 und e4 mit 10 zu 1 an. Der Wert α ist 1.0 und
für β wird 0.65 angegeben. Die beiden darauf folgenden Parameter bestimmen
resmax und repmax und RI bestimmt die Anwendung von Resubmission Impact
im Enactment Verfahren für diesen Workflow.
3.4 Scheduling-Komponente
Diese Komponente weist eine enge Kohäsion mit der Ausführungskomponente
auf. Hier befinden sich die Implementierungen von HEFT, HEFT-Replication,
Replicate All und Resubmission-Impact. Die Schnittstelle dieser Komponente bildet die Klasse SchedulingExecutorFactory. Eine Klasse welche Objekte vom Typ Executor zurückgibt. Das Executor Interface definiert die Methode public Schedule executeHEFT(). Jeder Executor implementiert die
Ausführung eines bestimmten Scheduling Verfahrens. Hier ist ebenfalls wieder
das Entwurfsmuster der Fabrikmethode verwendet worden. Im Folgenden werden die Implementierungen der Scheduling Algorithmen beschrieben, für welche
jeweils ein Executor bereitgestellt ist.
3.4.1 HEFT-Implementierung
Eingabeparameter und Bedingungen
Die Klasse HEFT realisiert den gleichnamigen Algorithmus und benötigt einen
Workflow vom Typ DAG als Eingabe. Zusätzlich zu diesem wird noch eine Liste, welche GridRepresentant Instanzen beinhaltet, übergeben. Diese Klasse
repräsentiert die Gridressourcen, die von GroudSim bereitgestellt werden, allerdings enthält sie einige Erweiterungen zu der ursprünglichen GridSite, die
in GroudSim enthalten ist. Der HEFT Algorithmus verlangt konkrete Informationen darüber, wieviele Jobs auf einer CPU ausgeführt werden. Zusätzlich
müssen die fixen Startzeitpunkte und Endzeitpunkte der Jobs auf der CPU
bekannt sein. Da eine GridSite lediglich eine Warteschlange besitzt, welche
22
3.4 Scheduling-Komponente
man ohnehin nur zur Laufzeit des Workflows benötigt, muss diese neue Klasse
eingeführt werden. Eine Instanz von GridRepresentant enthält ein Array mit
Objekten vom Typ CPUTimeTable, welche die Prozessoren repräsentieren. Diese
Objekte beinhalten, nach einer korrekten Ausführung von HEFT, die Knoten
in Form von GraphNode Instanzen mitsamt ihren Start- und Endzeitpunkten,
welche dem jeweiligen Prozessor zugeteilt sind.
Algorithmus
Der Algorithmus verhält sich so wie es in den theoretischen Grundlagen beschrieben worden ist, allerdings mit kleinen Ausnahmen welche im Detail beschrieben werden. Die Instanz von HEFT erzeugt eine Liste der Knoten, basierend
auf den jeweiligen Werten von ranku . Diese wird anschließend abgearbeitet indem pro Knoten in einer Schleife über alle GridRepresentat Objekte und ihre
Prozessoren (CPUTimeTable-Instanzen) iteriert wird, um die minimale Startzeit des jeweiligen Knotens zu ermitteln. Allerdings gibt es hier eine kleine
Änderung. Es ist eine Standarddauer für die Übertragung der Daten in der
Klasse EngineConfig definiert. Die Werte cmi,j und ci,j sind somit fix vorgegeben. Die Berechnung von EST wird von HEFT und den CPUTimeTable Instanzen
geteilt durchgeführt. Die Klasse HEFT übernimmt die Bestimmung des minimalen Startzeitpunktes sti für den Knoten ni , zu diesem alle Vorgänger beendet
und die Daten übertragen worden sind:
sti =
max
nm pred(ni )
(AF T (nm ) + cm,i )
Die Klasse CPUTimeTable bestimmt dann die frühestmögliche Laufzeit aufgrund
dem Zeitanteil, den die bereits zugeteilten Knoten konsumieren.
EST (ni , pj ) = max(pavailable[j], sti )
In diesem Fall ist pj eine Instanz von CPUTimeTable, welche diesen Wert berechnet. Zur Bestimmung von pavailable[j], wird in der Klasse CPUTimeTable
über alle zugeteilten Knoten nrk iteriert und versucht einen Startzeitpunkt
AF T (nrk ) zu finden, welcher die Bedingung
AF T (nrk ) + AST (nrk+1 ) >= sti + durationi
erfüllt. Wobei durationi die zufor berechnete Ausführungsdauer eines Knoten
auf dem jeweiligen Prozessor in Sekunden angibt. Sei powerpj die Anzahl an
MIPS für pj und instructionsi die Problemgröße für ni so ergibt sich der Wert
für durationi wie folgt:
durationi = instructionsi /powerpj
Nach der Berechnung ergibt sich pavailable[j] = AF T (nrk ). Es wird spätestens
beim letzten Knoten nrk , der pj zugeteilt worden ist, ein AF T -Wert ermittelt, welcher die oben angeführte Bedingung erfüllt. Die Berechnung von AF T
und AST erfolgt nach der Ermittlung von EST (ni , pj ) für alle pj . Die Werte für AF T und AST , sowie den Identifikationsstring des GridRepresentantObjektes welches EST minimiert, speichert der Algorithmus im Knoten, also
23
3 Implementierung
im Objekt der Klasse GraphNode. Der dem Knoten zugeteilte Prozessor speichert sich eine Referenz auf das zugehörige GraphNode Objekt, sowie dessen
fixe Start- und Endzeitpunkte. Diese Informationen werden benötigt, um den
nächsten freien Zeitschlitz pavailable[j] zu berechnen.
Zusätzlich zu diesen Werten werden noch die Gesamtkosten cost berechnet die
der Workflow insgesamt verbrauchen würde. Dabei wird die Anzahl der Instruktionen eines Knoten instructionsi mit den Kosten pro Instruktion costsP erInstr
für die zugeordnete GridSite multipliziert. Der Wert cost ergibt sich dann aus
der Summe der Kosten pro Knoten. Daraufhin berechnet der Algorithmus noch
den kritischen Pfad makeSpan, also die erwartete Gesamtlaufzeit des Algorithmus. Dabei wird einfach der maximale AF T Wert ermittelt. Der Rückgabewert
bei einem erfolgreichen Durchlauf des Algorithmus, ist ein Objekt der Klasse
Schedule, welches die Liste der GridRepresentant Instanzen, den Workflow,
den makeSpan und die Gesamtkosten cost beinhaltet.
3.4.2 HEFT-Replication-Implementierung ohne erneutes Scheduling
Der HEFT-Replication Algorithmus ist in einer Klasse HEFTReplication implementiert. Es gibt zwei verschiedene Versionen. Die Erste kommt beim ResubmissionImpact Verfahren zum Einsatz, die Zweite beim Erneuten Scheduling während
des Enactment Verfahrens.
Der HEFT-Replication Algorithmus basiert auf dem normalen HEFT Verfahren, daher ist die Implementierung analog zu der von HEFT und befindet sich in
der Methode mapNodeOnResources(). Sind allerdings AF T und AST für einen
Knoten in der Liste erfolgreich berechnet, so ruft der Algorithmus zusätzlich
die Instanzmethode checkAndReplicateParents() der Klasse GraphNode auf.
Diese Überprüft alle Vorgänger, ob ihre Replikas erzeugt und nun den Ressourcen zugeteilt werden können. Falls der Algorithmus für eine Instanz von
GraphNode Replikas erzeugen muss, so ruft HEFT Replication auf diesem Objekt die Methode generateReplicas() auf. Es werden repi Replikas erzeugt,
wobei jeder Replikaknoten, welcher als solcher gekennzeichnet ist, eine Referenz auf seinen Erzeuger erhält. Nach der Generierung der Replikas, ruft der
Algorithmus die Methode mapNodeOnResources() für jeden Replika auf. Man
kann dem Algorithmus von außen mitteilen, ob jeweils der erste Replika eines
Knotens auf eine andere Gridressource zugeteilt werden soll als der Erzeuger,
selbst wenn diese Ressource die Laufzeit des Workflows minimieren würde. Die
Variante des Algorithmus, welche zusätzliche Faktoren besitzt, ist im Kapitel
über das Dynamic Enactment Verfahren beschrieben.
3.4.3 Resubmission-Impact Implementierung
Die Implementierung dieses Algorithmus ist in der Klasse RIHeuristic definiert. Die Methode resubmissionImpact() realisiert den Ablauf des Verfahrens. Zunächst berechnet HEFT den kritischen Pfad des unmodifizierten Workflows. Danach ruft der Algorithmus die Methode evaluateDifferences() auf,
welche rekursiv durch den Graphen iteriert. Dabei erfolgt bei jeder Rekursion
die Berechnung von instructions0i . Diesen Wert speichert Resubmission Impact
24
3.4 Scheduling-Komponente
im jeweiligen Objekt der Klasse GraphNode statt dem alten Wert instructionsi ,
bevor ein erneuter Aufruf von HEFT erfolgt. Die jeweiligen Differenzen di werden in einer Liste gespeichert. Die Berechnung von RIi und ri erfolgt nach dem
beschriebenen Verfahren. Anschließend speichert Resubmission Impact diese
Werte ebenfalls in dem zugehörigen Objekt der Klasse GraphNode. Zuletzt erfolgt der Aufruf von HEFTReplication, wobei die Klasse GraphNode innerhalb
des Algorithmus soviele Replikas erzeugt, wie die zuvor gespeicherte Zahl ri
vorgibt. Es wird ein Objekt der Klasse Schedule zurückgegeben.
3.4.4 Parallelisierung von Resubmission-Impact
Die Berechnung der RIi Werte während des Resubmission Impact Verfahrens ist
sehr zeitaufwendig, da für jeden Knoten ni HEFT ausgeführt werden muss. Die
Länge der Ausführungszeit ist somit proportional zur Anzahl der Knoten. Die
Schleife zur Berechnung der Variablen instructions0i und des neuen kritischen
Pfades hef ti kann man allerdings sehr gut parallelisieren. Die Berechnungen von
instructions0i und di erfolgen für jeden Knoten getrennt. Um die Ausführung
des Resubmission Impact Verfahrens zu parallelisieren, muss man allerdings
den HEFT Algorithmus für Nebenläufigkeit optimieren. Die ursprüngliche Variante in der Klasse HEFT greift lesend und schreibend auf die Instanzen von
GraphNode zu. Der Algorithmus speichert nach jeder Abarbeitung eines Knotens, dessen, für diesen Durchlauf von HEFT, ermittelten AST und AF T Werte
in den jeweiligen Instanzen. Es würde somit zu gravierenden Inkonsistenzen
kommen, wenn mehrere Versionen von HEFT parallel auf AST und AF T , lesend
sowie schreibend, zugreifen könnten. Ein weiteres Problem stellt der Zugriff auf
die GridRepresentant Objekte dar, welcher ebenfalls schreibend und lesend
erfolgt, da der bestehende Algorithmus in den CPUTimeTable-Objekten die Referenzen für die Knoten speichert.
Parallelisierung von HEFT
Die Modifizierung des ursprünglichen Algorithmus in HEFT, wurde in der Klasse ParallelHEFT vorgenommen. Die Felder ranku , AST und AF T , dürfen in
den GraphNode-Objekten nicht geschrieben und gelesen werden wenn mehrere HEFT Algorithmen gleichzeitig auf den Workflow zugreifen. Es bieten sich
zwei Lösungen an. Die Erste wäre den gesamten Workflow für jede nebenläufige
Durchführung von HEFT zu kopieren. Dies würde allerdings die Speicherkapazitäten der Rechner zu schnell auslasten. Diese Implementierung verwendet deshalb die zweite Variante, welche nur die Felder ranku , AST und AF T kopiert
und in einem Array speichert. Das Speichern der Identifikationsnummer der
GridSite, welche EST für einen bestimmten Knoten minimiert, lagert der Algorithmus ebenfalls aus. Die Referenzen werden nun in einer Hashtabelle abgelegt und nicht mehr in den jeweiligen Instanzen. Die CPUTimeTable-Objekte pro
GridRepresentant müssen allerdings für jeden Thread kopiert werden, weshalb
es in der Klasse GridRepresentant eine Methode getThreadLocalCPUTimeTables()
gibt. Dieser Methode übergibt der ausführende Thread eine eindeutige Identifi-
25
3 Implementierung
kationsnummer, damit man die zugehörigen Ressourcen für die jeweilige Version
von HEFT identifizieren kann. Es gibt pro Ausführung von HEFT einen eigenen Thread, der eine eindeutige Identifikationsnummer besitzt. Das Ergebnis
ist, dass ParallelHEFT nur mehr die Gesamtlaufzeit makeSpan verpackt in
einem Schedule Objekt an den Aufrufenden ausliefert.
Aufteilung der Arbeit durch RIWorker
Um die Schleife im Resubmission Impact Algorithmus, in welcher die Werte für di errechnet werden, zu parallelisieren, muss man die Ausführung von
ParallelHEFT in Threads verlagern. Dafür zuständig ist die Klasse RIWorker
welche von Runnable erbt. Jede Instanz dieser Klasse wird von
ParallelRIHeuristic erzeugt, in welcher die parallele Version von Resubmission Impact implementiert ist. Zunächst erzeugt der Algorithmus v + 1
Instanzen, wobei v die Anzahl an Knoten darstellt. Anschließend speichert
ParallelRIHeuristic die Objekte in einem ThreadPool mit fixer Größe. Die
Anzahl der Threads welche parallel ausgeführt werden, kann in der Klasse
EngineConfig spezifiziert werden. Jede Instanz von RIWorker erhält die Ressourcen, den Workflow und einen Knoten von welchem der RIi Wert bestimmt
werden soll. Diese Objekte rufen nun den parallelen HEFT Algorithmus auf
und speichern den kritischen Pfad hef ti . Will man di schon in den jeweiligen
RIWorker Instanzen berechnen, so benötigt man den Wert von hef t. Allerdings
würde es, wenn der erste Aufruf von HEFT nicht parallelisiert wäre um hef t
zu berechnen, etwas an Performance kosten. Aufgrund von Amdahls Gesetz ist
der Geschwindikeitsgewinn einer Applikation umso höher, je geringer der serielle Programmanteil ist. Es werden somit die di Werte nicht in den Threads
gespeichert, sondern die jeweiligen hef ti Werte einer Klasse RICallback abgelegt. Dies ist auch der Grund, warum man v + 1 Threads erzeugt. Ein RIWorker
berechnet den Ursprünglichen hef t Wert, ohne Erhöhung der Instruktionszahl
des Knoten. Die Instanz welche den parallelen Resubmission Impact Algorithmus repräsentiert, ruft nachdem die Threads abgearbeitet werden die Methode
getDifferences() im Objekt von RICallback auf. Dabei wird solange gewartet bis alle Threads ihre Ergebnisse eingetragen haben. Die Berechnung der
jeweiligen di erfolgt in der Klasse RICallback, woraufhin schließlich eine Liste mit den jeweiligen Werten an ParallelRIHeuristic zurückgegeben wird.
Ab hier unterscheidet sich die nebenläufige Variante von Resubmission Impact
nicht mehr von der seriellen. RIi und repi Werte können nun nach dem Standardverfahren berechnet werden.
3.5 Die Ausführungskomponente
Dieser Teil des Programms beinhaltet den Enactmet Algorithmus, sowie Klassen
welche auf GroudSim zugreifen. Die Komponente unterstützt die Alloziierung
von Ressourcen, Jobs können an die angelegten Ressourcen gesendet werden und
es wird entsprechend auf Ereignisse innerhalb von GroudSim reagiert. Somit
kann man diese Komponente in zwei Teile zerlegen. Der Erste Teil ist für den
26
3.5 Die Ausführungskomponente
Enactment Algorithmus zuständig, der zweite Teil für die Kommunikation mit
GroudSim.
3.5.1 Schnittstelle zu GroudSim
Die Klassen, welche von GroudSim bereitgestellt werden, sollten möglichst stark
von dem Workflowsimulator abgekapselt sein. Diese Vorgehensweise ermöglicht
eine geringe Kopplung zwischen beiden Programmen. Es gibt eine Fassadenklasse namens GroudSimFacade, welche die Schnittstelle implementiert. Nach
außen werden alle Methoden angeboten, die für die Kommunikation mit GroudSim nötig sind. Die Fassade gibt nur Objekte, die nicht in GroudSim vorkommen zurück, wie z.B. GridRepresentant Instanzen. Jegliche Klassen die mit
GroudSim kommunizieren, werden von der Fassadenklasse verwendet. Die direkte Interaktion mit GroudSim findet in der Klasse GridUser statt. Hier werden die GridSite Insanzen alloziiert und Jobs gesendet. Des Weiteren reagiert
diese Klasse auf Ereignisse von GroudSim, wie z.B. JobActivatedEventTypeEvents, indem entsprechende Methoden, welche der GridUser implementiert,
von GroudSim aufgerufen werden. Die Fassadenklasse bildet bei jedem Sendevorgang GraphNode Instanzen auf GroudJob Objekte ab. Tritt dann ein entsprechendes Event auf, das einen GroudJob beinhaltet, so gibt die Schnittstelle nach
außen nur die Instanz des zugehörigen GraphNode zurück. Die Schnittstelle ist
für die Weiterleitung von Events an die DynamicEnactmentEngine verantwortlich, sowie für die Generierung von neuen Events durch die Klasse Submitter
und DynamicEnactmentEngine.
3.5.2 Implementierung des Enactment Verfahrens
Das Kernstück des Workflowsimulators befindet sich in der Klasse
DynamicEnactmentEngine. Diese beinhaltet eine Instanzmethode namens simulate().
Der Aufruf dieser Methode markiert den Beginn der Simulation. Zuerst überprüft
der Algorithmus welches Verfahren angewandt werden soll. Man kann den Scheduling Algorithmus für das initiale Schedule mithilfe des letzten Parameters in
der CSV Datei zur Workflow-Generierung bestimmen. Implementiert sind Versionen für HEFT, Resubmission Impact und Replicate All. Die ursprüngliche
Version, welche auch in den theoretischen Grundlagen besprochen worden ist,
beinhaltet Resubmission Impact. Das Rescheduling Verfahren kommt nur bei
der Variante mit Resubmission Impact zum Einsatz.
Enactment mittels Resubmission Impact
Die Implementierung dieses Algorithmus ist über diverse Methoden verteilt,
da während der Ausführung die Kontrolle an GroudSim abgegeben wird. Die
(c)
Werte für tr und td ergeben sich aus dem in den Grundlagen beschriebenen Verfahren, nachdem der Algorithmus für die parallele Version von Resubmission Impact aufgerufen worden ist. In der Instanz von DAG, dem aktuellen
Workflow, ruft Dynamic Enactment die Methode getFirstNode() auf, welche
den Wurzelknoten zurückgibt. Nun wird dieser mitsamt seinen Replikas für die
Ausführung an GroudSim übermittelt. Sobald der zugehörige GroudJob seinen
27
3 Implementierung
Status wechselt, protokolliert das Programm dies mit und Enactment reagiert
auf die Veränderung. Zudem wird protokolliert wieviele Kosten der jeweilige
Knoten verursacht hat und wie hoch die Gesamtkosten für die Ausführung des
Worklfows bereits sind. Insgesamt gibt es 3 entscheidende Ereignisse in der
Ausführung des Algorithmus.
Job schlägt Fehl Bei diesem Ereignis wird zunächst abgefragt, ob es noch Replikas gibt die in GroudSim ausgeführt werden, d.h. deren Status im Moment
auf running gesetzt ist. Ist dies der Fall, so wartet Enactment bis ein weiteres
Ereignis eintrifft. Dies passiert indem die Kontrolle an GroudSim abgegeben
wird. Finden viele Ausfälle von Ressourcen statt, so wird es vorkommen, dass
ein Knoten welcher fehlschlägt keine Replikas mehr besitzt die noch simuliert
werden. In diesem Fall fragt der Algorithmus ab ob der Knoten bereits resmax
mal gesendet worden ist. Ist diese Bedingung erfüllt, so bricht die Simulation
ab und der Status des Workflow wird auf failed gesetzt. Bevor die Simulation
abbricht, müssen alle Jobs, welche sich noch in der Ausführungsphase befinden
abgebrochen werden, um die entstandenen Kosten ermitteln zu können. Dies
betrifft alle Knoten deren Status auf submitted, queued oder running gesetzt
ist. Befindet sich die Simulation bereits in der Phase, in der alle verbleibenden
Knoten abgebrochen worden sind, so sendet der Algorithmus den Knoten nicht
mehr erneut. Ansonsten leitet der Algorithmus den Knoten an die Fassadenklasse GroudSimFacade für eine erneute Ausführung weiter.
Job ist erfolgreich abgearbeitet Nach Autreten dieses Ereignisses überprüft
Dynamic Enactment, ob die Simulation beendet werden muss. Ist dies der Fall
so wird die Ausführung aller verbleibenden Knoten abgebrochen und der Algorithmus protokolliert die Kosten dieser Knoten. Ansonsten fragt der Algorithmus ab ob es noch Replikas gibt, welche sich in der Ausführungsphase befinden. Ist der Status eines Replikas submitted, running, oder queued, so muss
dieser abgebrochen werden. Besonderes Augenmerk liegt hier auf Knoten, welche sich im Zustand running befinden. Es könnte passieren, dass zwei Knoten
gleichzeitig mit der Ausführung fertig werden. Darum wird jeder Knoten der
running als Zustand besitzt, in ein HashSet eingefügt. Falls nun der Algorithmus das JobFinishedEventType Ereignis für diesen Knoten abarbeitet, wird
dieser Knoten nicht mehr berücksichtigt, er kann kein erneutes Scheduling des
Workflows verursachen. Sind alle Replikas des ursprünglichen Knoten behandelt, so überprüft der Simulator ob es sich bei dem Knoten um den letzten im
Graphen handelt. Falls dem so ist, beendet Dynamic Enactment den Workflow
wieder sachgemäß. Ist dies nicht der Fall, so wird überprüft ob ein erneutes
Scheduling des Workflows nötig ist. Für das erneute Zurodnen der Ressourcen verwendet der Algorithmus das RI-Rescheduling Verfahren. Im Anschluss
entscheidet der Simulator darüber, welche Nachfolgeknoten nj succ(ni ) des
abgearbeiteten Knotens ni gesendet werden können. Sind alle Vorgänger von
nj bereits fertig mit der Ausführung, so sendet der Simulator nj mit all seinen
Replikas an GroudSim.
28
3.5 Die Ausführungskomponente
Job ist Abgebrochen Hier wird überprüft ob der Knoten der Letzte noch zu
Beendende ist, falls die Ausführung des Workflows fehlgeschlagen ist und die
Abarbeitung abgebrochen werden muss.
Erneutes Scheduling mit Resubmission Impact
Die Variante von RI-Rescheduling, die in den theoretischen Grundlagen beschrieben worden ist, kommt während Enactment zum Einsatz. Dazu wird
in der zugehörigen Executor Instanz des Rescheduling-Algorithmus der Wert
von repi für jedes GraphNode Objekt im Workflow entsprechend angepasst, bevor Heft-Replication ausgeführt wird. Die Version von HEFT Replication die
man hier für das Rescheduling verwendet, befindet sich ebenfalls in der Klasse
HEFTReplication, allerdings gibt Resubmission Impact im Konstruktor noch
eine boolesche Variable an die aufzeigt, dass die Instanz von HEFTReplication
für Reschedulingzwecke benutzt wird. Zusätzlich übergibt der Algorithmus beim
Erzeugen des Objektes noch die aktuelle Simulationszeit time. Die Variante des
Algorithmus unterscheidet sich dadurch, dass nur Knoten berücksichtigt werden, welche noch nicht an GroudSim gesendet worden sind. Die aktuelle Simulationszeit begrenzt den minimal möglichen EST -Wert, so dass sich folgende
Formel ergibt:
n
o
EST (ni , pj ) = max pavailable[j], max
(AF T (nm ) + cm,i ), time
nm pred(ni )
3.5.3 Weitere Eingabedateien anhand von Beispielen erklärt
Nachdem nun die Grundkonzepte des Programms dargestellt worden sind, können
die Eigenschaften der 2 weiteren Eingabedateien anhand von Beispielen besprochen werden.
1
grid_site_x; 1; 2000; 10; 1; 100000000; 9.6; 0.1; 10.0; 0.6; 1.0;
Dies ist ein Ausschnitt aus der Datei welche benötigt wird um Grids zu erstellen.
Der Name der GridSite kann willkürlich gewählt werden. Danach folgt die
Anzahl der Instanzen welche von dieser GridSite erzeugt werden sollen, in
diesem Fall ist der Wert 1. Der nächste Parameter 2000 bezieht sich auf die
Rechenleistung eines jeden Prozessors in Millionen Instruktionen pro Sekunde.
Danach wird die Gesamtanzahl an Prozessoren mit 10 festgelegt. Das Ausführen
von Instruktionen kostet Geld, somit muss man eine Zahl angeben die das
Verhältnis zwischen Kosten und Instruktionen angibt. In diesem Fall ist das
Verhältnis 1 : 1. Würde man hier den Parameter 10 übergeben, so wäre das
Verhältnis 1 : 10. Die weiteren Parameter bestimmen die mittlere Zeit zwischen
Fehlern (MTBF), die Fehlergröße, d.h. wieviele Prozessoren im Durchschnitt
ausfallen und die Dauer eines Fehlers. Diese werden GroudSim übergeben.
1
2
3
threadNumber=2
printWorkflows=true
maxRescheduleCycle=10
29
3 Implementierung
4
5
6
7
simulateFailures=true
instructionNumForBottomDummyNode=1
instructionNumForTopDummyNode=1
instructionNumForNode=10000000
Dieser Ausschnitt ist der Property Datei entnommen. Man kann diverse Parameter konfigurieren, welche alle in der Klasse EngineConfig vordefiniert worden sind. Gibt man für einen Parameter keinen Wert an, so wird er mit dem
Standardwert aus der Klasse EngineConfig initialisiert. Die Schlüssel Werte
Paare werden nun, von oben nach unten gelesen, beschrieben. Arbeitet man
auf einem Zweikern Prozessor, so empfiehlt es sich die Zahl mit 2 zu initialisieren. Der nächste Parameter bestimmt, ob der erzeugte Workflow auf der
Kommandozeile ausgegeben werden soll. Der Faktor cmax wird mit 10 gleichgesetzt, zusätzlich gibt die Datei an, dass Fehler simuliert werden sollen. Müssen
zusätzliche Knoten an der Wurzel, oder am Ende der Graphen angehängt werden, z.B. bei Povray und LDPMC, so geben die nächsten beiden Werte die
Anzahl an Instruktionen in diesen Knoten vor. Die oben eingeführte Variable
instr wird durch den letzten Parameter dargestellt.
30
4 Experimente
4.1 Performancetest
Abbildung 4.1: Performancetest: Zeiten in Sekunden angegeben
In dieser Tabelle ist ein Performancetest veranschaulicht. Das Experiment wurde auf dem Server kreusspitze.dps.uibk.ac.at durchgeführt. Der Rechner
besitzt insgesamt 8 Dual Core AMD Opteron 880 Prozessoren mit jeweils einer
Taktrate von 2400 Mhz. Es wurden Workflows vom Typ Wien2k mit einer fixen
Breite von 250 Knoten verwendet. Als Beispielressourcen wurden 4 GridSites
mit 10 Prozessoren und eine GridSite mit 5 Prozessoren verwendet. Die Anzahl
an Iterationen in Wien2k wurde jeweils so angepasst dass sich Gesamtgrößen
von 1006, 2012, 2515 und 3521 Knoten ergaben. Das Ergebnis zeigt eine deutliche Senkung der Laufzeit des Programms bei Verwendung von 6 Threads bei
hoher Problemgröße. Wurde das Programm mit 6 parallel laufenden Threads
abgearbeitet, so ergab sich eine Laufzeit von 115005 Millisekunden. Unter Verwendung von einem Thread für das Resubmissoin Impact Verfahren ergab sich
eine Laufzeit von 592097 Millisekunden. Man kann erkennen, dass die Simulation mit 6 Threads nahezu um den Faktor 6 schneller ist als die Simulation mit
nur einem Thread.
31
4 Experimente
4.2 Kosten- und Laufzeitenvergleich verschiedener
Fehlerszenarien
In diesem Experiment wurden insgesamt 60 Workflows auf 5 GridSites mit
jeweils 15 Prozessoren gescheduled und abgearbeitet. Es wurden 30 Wien2k
Graphen und 30 LDPMC Graphen simuliert. Die Ausführung wurde in 3 Fehlerszenarien mit verschiedenen Werten für die MTBF (mittlere Zeit zwischen
Fehlern) unterteilt. Es sind jeweils Zeiten von 4 Stunden (unstabile Ressourcen), 18 Stunden (normale Ressourcen) und 5 Tagen (stabile Ressourcen) ausgewählt worden. In jedem Szenario sind jeweils 10 Workflows vom Typ Wien2k und 10 Workflows vom Typ LDPMC abgearbeitet worden. Dabei wurden
pro Workflowtyp 5 Graphen einmal mittels Replicate All und einmal mittels
Resubmission Impact an die Ressourcen gescheduled. Die 5 Workflows sollten
jeweils unterschiedliche Gesamtlaufzeiten von ca. 7-8 Stunden bis zu 14 Tagen
beanspruchen. Die Laufzeiten wurden hier gleichmäßig verteilt, so dass sich im
Schnitt Abarbeitungszeiten von 7-8 Stunden, dreienhalb Tagen, sieben Tagen,
elf Tagen und 14-15 Tagen ergaben. Je nach Fehlerszenario ergibt sich eine unterschiedlich starke Verzögerung der Laufzeiten. Die Anzahl der Knoten für die
5 LDPMC und Wien2k Workflows befindet sich im Bereich von 63 bis 2646. Die
Einzelknoten in Wien2k erhalten eine höhere Problemgröße als die parallelen
Knoten. Der Faktor β für die Berechnung der Problemgröße ist hier 0.65. Dieser Faktor wurde so gewählt, damit Resubmission Impact nicht allen Knoten
in der zweiten und vierten Ebene eines Blockes einen hohen Wert für RIi zuteilt. Zugleich muss deshalb bei den LDPMC Graphen die Problemgröße aller
Knoten vergrößert werden, damit sich bei gleicher Knotenanzahl eine ähnliche
Laufzeit wie bei Wien2k ergibt. Dies ist deshalb von Nöten, da die Anzahl der
Ebenen bei LDPMC geringer als bei Wien2k ist. Jeder Graph wurde so konstruiert, dass sich maximal 32 parallele Knoten in einer Ebene befinden. Deshalb
ist die Ebenenanzahl bei einem LDPMC Graphen viel kürzer als bei Wien2k.
Für die Variablen resmax und repmax wurde jeweils ein Wert von 4 vergeben.
Ziel dieses Experiments ist das Aufzeigen der Tatsache, dass Replicate All hohe Kosten im Vergleich zu RI verursacht. Die Eigenschaft, dass RI auch mit
knappen Ressourcen auskommt, sollte hier ebenfalls aufgezeigt werden, sowie
die Auswirkung von Fehlern auf Kosten und Laufzeit der Workflows.
4.2.1 Erfolgsrate
Die Erfolgsrate gibt an, wieviele Workflows erfolgreich abgearbeitet worden
sind. Bei Wien2k ist die Erfolgsrate in allen Fehlerszenarien konstant 1. Bei
LDMPC ergibt sich eine Erfolgsrate von 40% im Falle von unstabilen Ressourcen. Dies kann man dadurch erklären, dass die Problemgröße in den Knoten von
LDPMC Workflows größer als in dem meisten Knoten von Wien2k Graphen ist.
Dadurch steigt die Chance eines erneuten Fehlschlags des gleichen Jobs, da dieser länger auf einer GridSite abgearbeitet wird, die MTBF allerdings knapp
bemessen ist. Der Simulator arbeitet die beiden kürzesten Workflows erfolgreich ab, allerdings schlägt die Abarbeitung der längeren Graphen fehl. Diese
Beobachtung wirkt sich auf die weiteren Messungen aus.
32
4.2 Kosten- und Laufzeitenvergleich verschiedener Fehlerszenarien
Abbildung 4.2: Angabe der Erfolgsrate in Prozent
4.2.2 Laufzeitenvergleich
In den beiden folgenden Grafiken ist jeweils die Summe aller Laufzeiten pro
Fehlerszenario und Schedulingverfahren dargestellt
Abbildung 4.3: Angabe der Laufzeit in Stunden
In dieser Grafik kann man einen Laufzeitunterschied zwischen den beiden Verfahren Resubmission Impact und Replicate All erkennen. Es soll hiermit gezeigt
werden, dass RI mit wenig, aber ausreichend vielen Ressourcen eine bessere
Laufzeit erzielt als Replicate All. Da die maximale Anzahl an Replikas 4 beträgt, erzeugt Replicate All sehr viele Replikas. Diese Knoten können nicht allesamt gleichzeitig abgearbeitet werden, weshalb sich eine stärkere Verzögerung
ergibt. Man sieht hier ebenfalls, dass die Laufzeit unter verwendung von un-
33
4 Experimente
stabilen Ressourcen bei beiden Verfahren stärker verzögert ist als bei stabilen
Ressourcen.
Abbildung 4.4: Angabe der Laufzeit in Stunden
Bei LDPMC fällt der Laufzeitunterschied zwischen RI und Replicate All ähnlich
auf wie bei Wien2k. Aufgrund der niedrigen Erfolgsrate bei stabilen Ressourcen
ergibt sich in Summe auch eine niedrige Laufzeit.
4.2.3 Kostenvergleich
Dargestellt werden hier die Kostensummen von allen 5 Workflows pro Fehlerszenario und Scheduling Verfahren. Die Kostensumme ist mit der Anzahl an
Instruktionen, welche pro GridSite abgearbeitet wurden gleichzusetzen, da die
Kosten für eine Instruktion genau 1 betragen. Multipliziert man die in der YAchse dargestellten Werte mit 109 so erhält man die Anzahl an Instruktionen.
Paradox erscheint hier zunächst, dass die Kosten für die Ausführung auf stabilen Ressourcen höher sind als auf unstabilen Ressourcen. Das liegt allerdings
unter anderem daran, dass viele Replikas erzeugt werden. Die GridSites sind
nahezu gleich schnell in der Abarbeitung der Instruktionen, somit werden die
Replikas eines Knotens fast zeitgleich mit der Abarbeitung fertig bevor sie abgebrochen werden. Die Kosten die sie verursacht haben werden somit sehr hoch
sein. Bei vielen Fehlern minimiert sich dieser Effekt allerdings. Replikas werden
zum Teil schon sehr früh durch Systemausfälle abgebrochen. Dies hat zur Folge,
dass sie nur wenige Kosten verursachen. Auffallend ist zudem, dass Replicate
All viel mehr Kosten verursacht als RI, da mehr Ressourcen von Replicate All
verwendet werden. Replicate All ist somit teurer wie RI, zudem ist in diesen
Szenarien die Ausführungszeit unter Verwendung des RI Verfahrens geringer
als bei Replicate All. Das RI Verfahren ist hier klar im Vorteil.
34
4.2 Kosten- und Laufzeitenvergleich verschiedener Fehlerszenarien
Abbildung 4.5: 109 Instruktionen
Bei den LDPMC Workflows ergeben sich für unstabile Ressourcen sehr wenige
Kosten. Man beachte, dass lediglich 2 Workflows abgearbeitet werden können,
die anderen 3 scheitern bei ihrer Ausführung. Dieses Verhalten hat eine geringere Kostensumme zur Folge. Man kann auch hier den Unterschied zwischen
RI und Replicate All sehr gut erkennen. Interessant ist zudem, dass zwischen
stabilen und normalen Ressourcen nur wenig Unterschied bezüglich der Kostensumme erkennbar ist. Die Summen sind bei diesem Workflowtyp etwas höher
als bei Wien2k.
Abbildung 4.6: 109 Instruktionen
35
4 Experimente
Zusätzlich zu der Kostensumme ist hier noch die Summe der verschwendeten
Kosten angegeben. Als solche werden alle Instruktionen von abgebrochenen oder
fehlgeschlagenen Knoten angesehen. Der bei den Kostensummen beschriebene
Effekt macht sich auch in dieser Grafik bemerkbar. Die Kostenverschwendung
ist bei unstabilen Resoucen geringer als bei normalen und stabilen Ressourcen. Dies kann wiederum dadurch erklärt werden, dass viele Knoten frühzeitig
beendet werden und somit wenig Kosten verursachen können. Beachtlich ist
ebenfalls, dass die verschwendeten Kosten fast mehr als die Hälfte der Gesamtkosten ausmachen wenn man hier mit den oberen Grafiken vergleicht. Die
Verschwendung ist bei Replicate All wieder deutlich höher als bei RI.
Abbildung 4.7: 109 Instruktionen
36
4.2 Kosten- und Laufzeitenvergleich verschiedener Fehlerszenarien
Bei LDPMC ergibt sich ein ähnlicher Effekt wie bei Wien2k. Bei den unstabilen Ressourcen können nicht alle Workflows abgearbeitet werden. Aus diesem
Grund ist die Kostensumme hier noch geringer als bei Wien2k. Analog wie bei
Wien2k werden ca. die Hälfte der Gesamtkosten verschwendet.
Abbildung 4.8: 109 Instruktionen
Als Vergleich wurde hier noch die Summe der Kosten aller Knoten, welche durch
Systemfehler fehlgeschlagen sind, angegeben. Man sieht, dass bei Verwendung
von unstabilen Ressourcen sehr viele Kosten durch Systemfehler verursacht werden. Bei normalen und stabilen Ressourcen ist dies nicht der Fall. Man sollte
nun sehr gut erkennen können, dass die meisten Kosten bei den stabilen und
normalen Ressourcen durch abgebrochene Knoten verursacht worden sind und
nicht durch Systemfehler. Die Unterschiede zwischen RI und Replicate All fallen
wieder deutlich auf.
37
4 Experimente
Abbildung 4.9: 107 Instruktionen
Beim LDPMC Graphen ist ein sehr ähnliches Ergebnis wie beim Wien2k Workflow zu beobachten.
Abbildung 4.10: 107 Instruktionen
38
5 Zusammenfassung
Workflow Execution Simulation ist ein Programm das Workflows erzeugen, effizient an erstellte Ressourcen verteilen und anschließend abarbeiten kann. Es
wurde versucht, auf Modularität zu achten. Es können ohne Einschränkungen
mehrere Workflowgeneratoren hinzugefügt werden. Die Implementierung der
Schedulingalgorithmen sieht keine besondere Struktur der Workflows vor. Der
Graph sollte lediglich aus einem Start- und einem Endknoten bestehen. Die
internen Eigenschaften des Programms können zudem sehr leicht mithilfe der
Property Datei eingestellt werden. Die Konfigurationsfreiheit ist nicht darauf
beschränkt, dass man den Programmcode manuell ändern muss. Alle wichtigen
Features wie Threadanzahl, Basisinstruktionsanzahl von Knoten, Fehlersimulation,. . . können konfiguriert werden. Dies ist allerdings auch von Nöten, da keine
grafische Benutzeroberfläche zur Verfügung gestellt wird. Ein wichtiger Punkt
war auch die Performance des Programms. Wie im ersten Experiment gezeigt
worden ist, kann das Scheduling eines Workflows sehr viel Zeit in Anspruch
nehmen. Der kritische Punkt ist hierbei der Resubmission Impact Algorithmus,
welcher HEFT für jeden Knoten aufruft. Es wurde versucht diesen Algorithmus
effizient zu parallelisieren, damit man auf Multiprozessorarchitekturen einen
Performancevorteil erzielen kann. Die Ausgabedateien verwenden das Format
CSV. Dies erleichtert das Parsen von tausenden Zeilen, die bei der Abarbeitung von vielen Knoten entstehen. Die im Anschluss durchgeführten Experimente sollen einen Einblick geben, dass man mit diesem Tool verschiedenste
Fehlerszenarien und Workflowtypen genau analysieren kann.
39
Literaturverzeichnis
[1] I. Foster. What is the grid? a three point checklist. 2002.
[2] Ian Foster, Carl Kesselman, Gene Tsudik, and Steven Tuecke. A security
architecture for computational grids. In Proceedings of the 5th ACM conference on Computer and communications security, CCS ’98, pages 83–92,
New York, NY, USA, 1998. ACM.
[3] Christian Baun, Marcel Kunze, Jens Nimis, and Stefan Tai. Cloud Computing - Web-Based Dynamic IT Services. Springer, 2011.
[4] Christian Baun, Marcel Kunze, and Viktor Mauch. The koala cloud manager: Cloud service management the easy way. In IEEE CLOUD, pages
744–745, 2011.
[5] Peter Mell and Tim Grance. The NIST Definition of Cloud Computing.
Technical report, July 2009.
[6] Alexandra Olteanu and Andreea Marin. Generation and evaluation of scheduling dags: How to provide similar evaluation conditions. Computer Science
Master Research, 1(1), 2011.
[7] Haluk Topcuouglu, Salim Hariri, and Min-you Wu. Performance-effective
and low-complexity task scheduling for heterogeneous computing. IEEE
Trans. Parallel Distrib. Syst., 13(3):260–274, March 2002.
[8] Kassian Plankensteiner and Radu Prodan. Meeting soft deadlines in scientific workflows using resubmission impact. IEEE Trans. Parallel Distrib.
Syst., 23(5):890–901, 2012.
40
Herunterladen