Universiteit van Amsterdam

advertisement
Universiteit van Amsterdam
Faculteit der Natuurwetenschappen, Wiskunde en Informatica
Bachelor Scriptie
Performance analyse van de parallelle Lattice Boltzmann simulatie
in Java met Ibis.
Student: M.V. Filatov
Begeleidende docent: A.G. Hoekstra
22 juni 2005
Inhoudsopgave
1. Inleiding···································································································································· 2
2. Applicatie ································································································································· 2
3. Ibis en GMI ······························································································································ 4
3.1 RMI ····························································································································· 4
3.2 Group Method Invocation ······················································································ 5
4. Implementatie··························································································································
4.1 Broadcast ···················································································································
4.2 Reduce ························································································································
4.3 Communicatie van de randpunten ·········································································
4.4 Synchronisatie en barrières ····················································································
6
7
7
8
8
5. Experimentele omgeving········································································································ 9
6. Experimenten··························································································································· 9
6.1 Experimenten op een cluster ··················································································· 9
6.2 Experimenten op meerdere clusters······································································· 10
7. Resultaten································································································································· 10
7.1 Performance metingen op een cluster ···································································· 10
7.2 Performance metingen op meerdere clusters························································ 13
8. Conclusie en discussie············································································································· 15
Dankwoord··································································································································· 15
Referenties···································································································································· 15
1
1. Inleiding
Veel wetenschappelijke berekeningen zijn vaak ingewikkeld maar vooral grootschalig[12, 13].
Er wordt met enorme hoeveelheden data gerekend. Verschillende simulaties vragen daarom
om veel rekenkracht en snelheid. Lattice Boltzmann simulatie van de vloeistof dynamica[16]
is een van zulke applicaties. Performance van een wetenschappelijke applicatie hangt sterk af
van de machine waarop deze applicatie wordt gedraaid. Maar èèn machine is niet genoeg om
wenselijke performance te halen. Parallel computing is een mogelijke oplossing voor de
performanceproblemen.
High-performance parallelle applicaties worden geoptimaliseerd voor betere
performance. Het efficiënt opdelen van een probleem in stukken (decompositie) en verdelen
van deze stukken over de beschikbare processors (mapping) is misschien het belangrijkste
onderdeel van het maken van een parallelle applicatie. De keuze voor een programmeer
omgeving valt vaak op C/C++ met MPI als communicatie interface.
Traditioneel wordt C met MPI (Message Passing Interface) beschouwd als een
standaard voor het schrijven van parallelle programma’s. De meeste applicaties zijn tot nu toe
met succes gemaakt in C of C++ met MPI. Maar er zijn natuurlijk ook andere middelen
beschikbaar voor parallel computing, zoals bijvoorbeeld Java. Java wordt vaak gezien als niet
efficiënt en traag voor de wetenschappelijke berekeningen. Er wordt echter hard gewerkt aan
het verbeteren van Java voor wetenschappelijk rekenen[17]. Java-Compilers zijn in staat een
efficiënte code te genereren en met JIT(Jist-in-Time) compiler worden vaak gebruikte
routines gecompileerd om performance te verbeteren. Bovendien zijn er verschillende
packages en systemen beschikbaar voor de high-peformance wetenschappelijke
applicaties[1,8].Ook het object georiënteerde programmeer model en portabiliteit maken Java
een geschikte programmeeromgeving voor wetenschappelijke applicaties.
De groeiende interesse om Java voor high-performance parallel comupintg te
gebruiken heeft enkele ontwikkelingen in dit gebied gestimuleerd. Zo is er bijvoorbeeld Ibis
ontwikkeld[2]. Het systeem stelt de gebruiker in staat om efficiënte parallelle applicaties in
Java te schrijven. Er zijn echter veel twijfels over prestaties van parallelle Java-applicaties.
Dat is ook begrijpelijk want de communicatie in Java is nog niet zo snel als in C met MPI [2]
In dit werk wordt de performance van een parallelle Java-applicatie geanalyseerd.
Dezelfde applicatie is in C++ met MPI geïmplementeerd. De prestaties van beide
implementaties worden met elkaar vergeleken. De vraag is dan natuurlijk of een parallelle
applicatie in Java een performance vergelijkbaar met C++ zal halen. Uit de resultaten van dit
onderzoek wordt duidelijk of Java een concurrentie kan maken voor C++ en MPI bij
wetenschappelijke berekeningen.
2. Applicatie
De applicatie die in dit onderzoek wordt gebruikt is een simulatie van de vloeistof dynamica.
Voor de simulaties van natuurlijke verschijnselen worden vaak cellulaire automata gebruikt[5,
14, 15]. Daarbij wordt het probleem gerepresenteerd als een verzameling van elementen (in
dit geval vloeistofdeeltjes). Elk element kan zich bevinden in een bepaalde toestand. De
toestand van een afzonderlijk element wordt bepaald door de toestand van andere elementen
in de buurt.
Voor de simulatie van de vloeistof wordt de Lattice Boltzmann Method (LBM) gebruikt[3,4].
Deeltjes bevinden zich in de knopen van een 3D-rooster. Elk element in het rooster is
verbonden met 18 van zijn buren (Zie Figuur1). Bij elke tijdstap verplaatsen deeltjes zich
naar een andere knoop en vervolgens botsen tegen andere deeltjes. Daarbij worden de
snelheden die deeltjes hadden verdeeld.
2
Simulatie van de vloeistof dynamica.
Figuur 1. Rooster in
LBM-simulatie
Deze methode wordt veel toegepast voor de simulaties van vloeistof dynamica. In de
simulaties kan de vloeistof door verschillende geometrische vormen stromen. In dit onderzoek
beperken we ons tot een simpele pijpstroming (Poisseule flow). Dat wil zeggen simulatie van
de vloeistof die door de pijp stroomt. In de simulatie zijn beide randen van de pijp met elkaar
verbonden zodat wat er aan de ene kant uitkomt gaat aan de andere er weer in(zogenaamde
periodiek randvoorwaarden). Aan de wanden van de pijp geldt dat de snelheid van de
stroming nul moet zijn (no-slip). In de rooster Boltzmann methode wordt no-slip gerealiseerd
met de Bounce Back regel: bij een botsing met de wand worden deeltjes teruggekaatst met
dezelfde snelheid. Dat is de simpelste methode voor het afhandelen van de randcondities en
deze wordt ook gebruikt in onze simulatie.
Voor de grote roosters, bijvoorbeeld 100x100x100, is de executietijd van de simulatie te lang
en groeit cubisch naarmate het rooster groter wordt. De rooster Boltzmann methode is echter
goed parallelliseerbaar[voor details, zie 4]. Dus de simulatie kan gedraaid worden op een
parallel systeem met betere performance. Data decompositie is een belangrijk onderdeel van
een efficiënt parallel programma. Er zijn verschillende decompositie methodes mogelijk
afhankelijk van de geometrie van de omgeving[6]. In het geval van pijpstoming is de simpele
slice decompositie goed genoeg. Het hele rooster wordt in slices gesplitst en elke processor
krijgt een slice om ermee rekenen. Alle slices zijn van hetzelfde grootte dus het werk word
gelijkmatig onder processors verdeeld. De rand punten van de locale roosters worden tussen
processors gecommuniceerd. (Zie figuur 2)
Pijpstroming
Decompositie
Processor 0
Processor 1
Processor 2
Communicatie van
de randpunten
Figuur 2. Pijpstroming,
decompositie en
randvoorwaarden
Periodieke
randvoorwaarden.
3
Er zijn al veel experimenten gedaan met Lattice Boltzmann Method op parallele systemen [6].
Alle applicaties waren in C/C++ met MPI geschreven. Een interessante vraag is natuurlijk hoe
zo’n simulatie in Java zal presteren. Tegenwoordig is het mogelijk om efficiënte parallelle
applicaties in Java te schrijven. Performance van zulke applicaties blijft een interessante zaak
om te onderzoeken.
3.Ibis en GMI
3.1 RMI
method()
resultaat
Referentie
Met zijn object georiënteerd programmeer model en portabiliteit is Java een aantrekkelijke
programmeer omgeving voor het schrijven van wetenschappelijke rekenprogramma’s. Er zijn
niet genoeg middelen in Java zelf om een goede parallelle applicatie te kunnen schrijven.
Alles waar Java over beschikt is RMI (Remote Method Invocation). Met RMI kunnen
methods van objecten op verschillende machines aangeroepen worden. Het aanroepen van een
method wordt gedaan via een referentie naar object. De aanroep wordt automatisch
doorgegeven naar een object op een andere machine. Daar wordt de method uitgevoerd en het
resultaat wordt teruggegeven. Zie figuur 3.
JVM 1
Object
JVM 2
Figuur 3. Aanroep van een method
op een andere machine
RMI heeft vele voordelen zoals het ondersteunen van “linked structures”. Dat houdt in dat bij
het doorgeven van alleen de root van een binaire boom de hele boom automatisch wordt
doorgegeven aan een object. Het grootste nadeel van RMI is dat het alleen synchrone pointto-point communicatie ondersteunt. Voor veel parallelle applicaties is de groepscommunicatie
zoals bijvoorbeeld de broadcast echter noodzakelijk. Implementatie van groepscommunicatie
met RMI is ingewikkeld en inefficiënt. Een ander nadeel is dat communicatie met RMI niet
efficiënt is. Daardoor is het veel lastiger om wenselijke speed-ups voor een parallelle
applicatie te halen.
Er is veel onderzoek gedaan naar efficiëntie van RMI en een aantal oplossingen zijn bedacht
om RMI te verbeteren.[9,10] Ibis[7] is een van deze oplossingen. Ibis, ontwikkeld aan de
Vrije Universiteit in de groep van Prof. Henri Bal, is niet alleen een optimalisatie van RMI.
Ibis ondersteunt ook verschillende programmeer modellen zoals GMI (Group Method
Invocation) en RepMI (Replication Method Invocation). Zie Figuur 4.
Op de figuur is de Ibis laag in grijs gerepresenteerd. Deze is verantwoordelijk voor alle
optimalisaties. Daar bovenop zijn een aantal programmeer modellen opgebouwd.
4
Figuur 4. De opbouw van Ibis
3.2 Group Method Ivocation.
De simulatie in dit onderzoek is met behulp van GMI [7]geïmplementeerd. Dit programmeer
model biedt alle mogelijkheden voor de groepscommunicatie waardoor het erg geschikt is
voor de Lattice-Boltzman simulatie.
In GMI is het mogelijk om referenties naar een groep van objecten te gebruiken. Met deze
referentie kan met alle objecten van de groep als een geheel worden gecommuniceerd. Daarbij
kunnen de objecten zich op verschillende machines bevinden. Zoals op figuur 5 te zien is
verwijst de referentie naar een groep van twee objecten.
Object
JVM 1
Groepsreferentie
Object 1
JVM 2
Groep van twee
objecten
Figuur 5. Groepsreferentie
naar objecten op andere
machines.
Object 2
JVM 3
Forwarding schema’s.
GMI biedt een aantal schema’s voor het doorgeven van methods aanroepen. Te weten:
- Single invocation
5
-
Group invocation
Personalized invocation
Combined invocation
Hier volgt een kleine beschrijving van de schema’s die in de huidige implementatie worden
gebruikt. In de sectie Implementatie worden deze schema’s aan de hand van voorbeelden
toegelicht.
Single invocation -
een method van één object van de groep wordt aangeroepen. Het object
is geïdentificeerd door de rank.
Group invocation - een method wordt aangeroepen bij alle objecten van de groep.
Combined invocation - een method wordt tegelijk door een aantal processen aangeroepen.
Alle aanroepen worden gecombineerd tot één aanroep die vervolgens
wordt aan de objecten van de groep doorgegeven.
Results handling
Zoals bij method forwarding zijn er in GMI verschillende schema’s beschikbaar voor het
afhandelen van de resultaten. Deze zien er als volgt uit:
- Discard results
- Return one result
- Forward results
- Combine results
- Personalize results
In deze applicatie wordt alleen discard results schema gebruikt. Zoals de naam al zegt worden
de resultaten van een method gewoon genegeerd. Zo hoeft het proces niet te wachten op een
resultaat en kan meteen doorgaan met rekenen.
Al deze schema’s zowel voor forwarding als voor results handling worden run-time
geconfigureerd. Allerlei combinaties van deze schema’s zijn ook mogelijk. Daardoor is GMI
een heel expressief en flexibel model waarmee complexe groepscommunicatie kan worden
gerealiseerd.
4. Implementatie
In deze sectie worden de verschillen tussen Java en C++ implementaties van de simulatie
besproken. De verschillen zitten voornamelijk in de manier waarop de communicatie is
gerealiseerd. Aan de hand van concrete voorbeelden worden MPI en GMI implementaties met
elkaar vergeleken.
Eerst geven we een globaal overzicht van de applicatie. In het onderstaande proces flow
diagram (Figuur 6) zijn de verschillende fases van de simulatie te zien. We concentreren ons
vooral op het communicatie gedeelte van het programma. Daarom zijn er een aantal
rekenstappen niet in het diagram opgenomen.
6
Initialisatie
Broadcast
parameters
Decompositie
Berekeningen
Communicatie
Verzenden van
de locale
domeinen
Simulatie
Reduce van de parameters.
Communicatie van de
randpunten
Figuur 6. Globale proces flow
diagram van de LBM-applicatie
In de Java implementatie wordt eerst een groep aangemaakt. Vervolgens maakt elk proces een
object aan. Dat object bevat de hele Lattice Boltzmann simulatie. Het object wordt aan de
groep toegevoegd. Alle objecten krijgen een groepsreferentie. Door middel van deze
referentie kunnen objecten met elkaar communiceren. De communicatie vindt plaats wanneer
de objecten methods van elkaar aanroepen. Elke method die bij de communicatie wordt
gebruikt moet eerst geconfigureerd worden. Bij de configuratie worden Forwarding en Result
handling schema’s voor de methods bepaald. Hoe de methods voor deze simulatie
geconfigureerd zijn wordt hieronder behandeld.
4.1 Broadcast
MPI beschikt over speciale functie voor de Broadcast - MPI_Bcast(). Deze functie wordt
expliciet door elk proces aangeroepen en een bericht wordt vervolgens aan iedereen
doorgegeven.
In GMI wordt Broadcast als een method geïmplementeerd. Deze method wordt door één
object aangeroepen bij alle andere objecten van de groep. Data die moet gebroadcast worden
is meegegeven als parameters voor deze method.De Broadcast method is als volgt
geconfigureerd.
Forwarding schema – group invocation
Result handling – discard results
4.2 Reduce
In de simulatie wordt reduce-operatie gebruikt om de waarde van alle processen te reduceren
tot één waarde. In dit geval wordt er met reduce de som van alle waarden berekend.
Door elk proces wordt in C++ MPI_Reduce() aangeroepen. De som van alle waarden wordt
berekend en doorgegeven aan één proces.
In GMI gebeurt hetzelfde. Elke proces roept Reduce() method aan een geeft een waarde mee.
Vervolgens worden alle waarden gecombineerd. Reduce() method is echter door de gebruiker
zelf geschreven en als volgt geconfigureerd.
Forwarding schema – combined invocation
Result handling – discard results
7
Zoals al eerder vermeld is houdt de combined invocation in dat alle aanroepen worden
gecombineerd tot één aanroep. De manier waarop de combinatie wordt gedaan wordt geheel
door de gebruiker bepaald. Dat is een groot verschil met MPI waar de gebruiker keuze heeft
uit beperkte aantal mogelijkheden voor de reduce-operatie, bijvoorbeeld o.a. som of minimum
van alle waarden.
4.3 Communicatie van de randpunten
Voor het uitwisselen van de randpunten van het locale rooster tussen processors wordt
MIP_Sendrecv() gebruikt. Elke processor communiceert met zijn twee buren. Voor dezelfde
communicatie worden in GMI methods gebruikt die als volgt zijn geconfigureerd:
Forwarding schema – single invocation
Result handling – discard results
Single invocation configuratie zorgt ervoor dat met dezelfde groepsreferentie een method van
één object(linker- of rechterbuur) wordt aangeroepen. Daarbij worden de randpunten
meegegeven als argument.
4.4 Synchronisatie en barrières
Doordat in GMI bijna alle methods, behalve reduce, niet expliciet door alle processen worden
aangeroepen moet er over de synchronisatie nagedacht worden. Bijvoorbeeld Broadcast
method wordt door één proces aangeroepen. De aanroep wordt doorgegeven aan alle objecten
in de groep. Maar de objecten zelf weten niet op welk moment in het programma de method
wordt uitgevoerd. Dus het is vaak nodig om te wachten totdat een method zijn werk gedaan
heeft en pas dan verder te gaan. De figuur 7 illustreert dit probleem.
Process 0
Bcast(params){
…
notify()
}
…
if (rank == 0){
Group.Bcast();
Wait();
…
Process 1
Bcast(params){
…
notify()
}
…
if (rank == 0){
Group.Bcast();
Wait();
…
Figuur 7. Synchronisatie bij het
aanroepen van methods
Zoals op de figuur te zien is wacht (wait() ) het hoofdproces totdat de Bcast() method is
uitgevoerd. Aan het einde roept de Bcast() method notify() aan om het hoofdproces “wakker
te maken”. Zonder deze notify()-wait() constructie bestaat er altijd de mogelijkheid dat een
method te laat of te vroeg wordt aangeroepen.
Dit probleem bestaat in MPI niet omdat alle processen die aan de communicatie deelnemen
MPI message passing routines expliciet aanroepen wanneer het nodig is.
Voor de synchronisatie van parallelle processen worden in C++ implementatie
MPI_Barrier()’s gebruikt. In tegenstelling tot MPI ondersteunt GMI geen barriers. In plaats
daarvan wordt er een “dummy” method gebruikt. Deze method doet niets en is
geconfigureerd als combined invocation. Omdat alle aanroepen bij de combined invocation
schema eerst gecombineerd moeten worden wachten alle processen totdat iedereen de barrier
8
method heeft aangeroepen. Bij de aanroep bevinden alle processen zich op hetzelfde punt in
het programma. Pas daarna kan ieder proces doorgaan met zijn werk.
Op het eerste gezicht lijkt de communicatie met GMI iets ingewikkelder voor de gebruiker in
vergelijking met MPI. Soms is dat wel zo want alle methods moeten handmatig
geconfigureerd worden en combiners voor de operaties zoals reduce worden door de
gebruiker zelf gedefinieerd. Aan de andere kant is GMI zo flexibel en expressief doordat het
veel ruimte biedt om verschillende communicatie schema’s te implementeren.
5. Experimentele omgeving
Alle experimenten werden op de DAS2 (Distributed ASCI Supercomputer) systeem
uitgevoerd. DAS2 bestaat uit 5 clusters. De eerste reeks experimenten werd op een cluster van
DAS2 gedaan. Deze cluster bestaat uit 32 nodes. Deze zijn door snelle Myrinet-2000 netwerk
met elkaar verbonden. Elke node heeft de volgende specificaties:
•
•
•
•
•
Twee 1-Ghz Pentium-III processors
1.5 GB RAM
80 GByte locale IDE disk
Myrinet interface kaart
Fast Ethernet interface (on-board)
Voor de experimenten op meerdere clusters werden de clusters van de Universiteit Leiden,
Technische Universiteit Delft, Vrije Universiteit (72 nodes) en Universiteit van Amsterdam
gebruikt. De communicatie tussen de verschillende clusters vindt plaats door middel van Fast
Ethernet.
Java applicatie is met IBM Java2 compiler 1.4.2 (met JIT-compiler aan) gecompileerd.De
keuze voor de IBM Java-compiler is gebaseerd op het feit dat de performance daarvan is veel
beter dan die van SUN JDK [11]. Voor de C++ versie is g++ (GCC) 3.2.3 compiler gebruikt.
6. Experimenten
6.1 Experimenten op een cluster.
In deze sectie worden de uitgevoerde experimenten beschreven. De applicatie heeft een aantal
parameters. Door deze parameters te variëren kan men de simulatie beïnvloeden. Een van de
parameters is de grootte van het rooster. Voor de experimenten zijn de roosters van 403, 803
en 1203 punten genomen. Er wordt telkens de executietijd per iteratie gemeten. Op deze
manier zijn beide implementaties makkelijk met elkaar te vergelijken. Ook kan men een
inzicht krijgen hoe de executietijd groeit naar mate het probleem groter wordt.
Het wegschrijven van de gegevens naar bestand is uitgeschakeld. De reden daarvoor is dat I/O
in Java aanzienlijk trager is dan in C++. Bovendien is er veel schijfruimte nodig om de output
van de simulatie te kunnen bewaren. Experimenten met grote rooster zouden niet lukken
omdat de schijfruimte gelimiteerd was tot 256 MB. Er wordt dus alleen reken- en
communicatietijd gemeten.
De metingen zijn gedaan voor 50 iteraties. Dat is genoeg om applicatie op de “optimale
snelheid” te krijgen en enkele statistieken over de metingen te verzamelen. Op de figuur 10 is
9
de gemiddelde executietijd per iteratie afhankelijk van het aantal iteraties afgebeeld. De eerste
iteratie in beide implementaties duurt het langst. Daardoor wordt het gemiddelde omhoog
getrokken. Na ongeveer 50 iteraties heeft de tijd van de eerste iteratie bijna geen invloed meer
op het gemiddelde. Het is wel mogelijk om de eerste iteratie buiten beschouwing te laten.
Maar het doel is om de echte applicatie te testen en de eerste iteratie hoort er natuurlijk bij. De
verschillen in deze grafieken worden verder in de sectie Resultaten besproken.
De simulatie wordt elke keer op verschillend aantal processors uitgevoerd. Tijd die nodig is
voor het uitwisselen van de randpunten tussen de processors wordt ook gemeten. Deze
communicatietijd is min of meer constant en is niet afhankelijk van het aantal processors. Er
wordt namelijk steeds tussen twee processors gecommuniceerd(communicatie van de
randpunten).
6.2 Experimenten op meerdere clusters
De tweede reeks van de experimenten is op de meerdere clusters van DAS2 uitgevoerd. We
willen analyseren hoe de performance van de simulatie beinvloed wordt doordat de applicatie
over de meerdere clusters is verdeeld. De simulatie wordt gedraaid op 2 en 4 clusters. De
processors die deelnemen aan de berekeningen zijn gelijkmatig over de clusters verdeeld. Dus
bijvoorbeeld voor de simulatie met 12 processors op 2 clusters worden er 6 processors op elke
cluster gebruikt. Om ervoor te zorgen dat processors op verschillende clusters elkaar kunnen
vinden word er op een cluster de ibis name server gestart. Alle processors maken dan een
verbinding met de name server en kunnen vervolgens met elkaar communiceren.
De metingen zijn gedaan alleen voor de Java implementatie. We vergelijken de speedup’s van
de applicatie op meerdere clusters. De speedup is gerelateerd aan de performance van de Javaapplicatie op een machine.
De resultaten van de metingen zijn in de volgende sectie gepresenteerd.
7. Resultaten
De resultaten van hiervoor beschreven experimenten worden in deze sectie besproken.
7.1 Performance metingen op een cluster
De volgende grafieken (zie figuur 8) representeren de resultaten van de executietijd metingen.
De trend op de grafieken is typisch voor een parallelle applicatie. Aanvankelijk is er een
sterke verbetering in de performance bij de toename van het aantal processors. Maar naar
mate het aantal processors groter wordt wordt de communicatietijd langer ten opzichte van de
rekentijd. In dit geval is de communicatietijd bijna constant dus de rekentijd wordt steeds
kleiner. Op een gegeven moment is de applicatie grotendeels bezig met de communicatie
tussen processors. De parallelle applicatie is dan niet meer efficiënt en wordt niet sneller door
het toevoegen van processors. Dat is vooral te zien bij de experimenten met de roostergrootte
van 40x40x40 want daar is de rekentijd het kleinst.
10
Executie tijd per iteratie (rooster grootte
80x80x80)
0,6
5
Tijd per iteratie (sec)
Tijd per iteratie (sec)
Executie tijd per iteratie (rooster grootte
40x40x40)
0,5
0,4
Java
0,3
C++
0,2
0,1
0
1
2
4
4
3
Java
2
C++
1
0
8 12 18 24 36
1
Aantal processors
2
4
8 12 18 24 36
Aantal processors
Tijd per iteratie (sec)
Executie tijd per iteratie (rooster grootte
120x120x120)
14
12
10
8
6
4
2
0
Java
C++
1
2
4
Figuur 8. Executietijd van de simulatie
afhankelijk van het aantal processors.
Verticale lijnsegmenten representeren de
standaarddeviatie.
8 12 18 24 36
Aantal processors
Het belangrijkste op deze grafieken is het verschil tussen twee implementaties. Javaimplementatie is bij alle experimenten sneller dan C++. Zoals al eerder werd vermeld (zie
figuur 6) is de simulatie in twee delen op te delen. De twee delen zijn de communicatie en
berekeningen. Om de oorzak van het performanceverschil te vinden worden de
communicatietijd en de rekentijd afzonderlijk gemeten. De resultaten van de metingen zijn op
de volgende grafieken gepresenteerd.
Eerst de communicatietijd. Op de figuur 9 is de gemiddelde communicatietijd van de
simulatie afgebeeld. De metingen zijn gedaan, net zoals andere experimenten, voor drie
verschillende roostergroottes.
Communicatietijd (sec)
Totale communicatietijd over 50
iteraties
12
10
8
Java/GMI
6
C++/MPI
4
2
Figuur 9.Totale
communicatietijd van de
simulatie
0
40
80
120
Roostergrootte
11
Hoe groter het rooster hoe meer randpunten moeten er overgestuurd worden. Op de grafiek is
de communicatietijd dan ook het langs bij het rooster van 120x120x120 punten. Daarbij wordt
een array van 120x120x1 punten overgestuurd. De communicatie verloopt iets sneller met
MPI dan met GMI. Dat komt overeen met de metingen in [2] en [7]. Op de eerste grafiek
( roostergrootte 40x40x40) van figuur 8 is ook duidelijk te zien dat de communicatieoverhead
van Java applicatie groter is dan van C++.
Het verschil in performance kan dus aan de rekensnelheid van Java en C++ liggen. Om dat te
controleren meten we de rekentijd van de applicatie. Er wordt rekentijd per iteratie gemeten.
Het aantal iteraties varieert van 1 tot 50. Dit experiment is uitgevoerd op één machine. Op de
figuur 10 zijn de resultaten van deze metingen te zien.
Executietijd afhankelijk van aantal iteraties
(rooster grootte 80x80x80)
8
6
Java
4
C++
2
Aantal iteraties
30
15
5
0
1
30
15
5
3
C++
10
3
Java
Executie tijd per iteratie
(sec)
1,6
1,4
1,2
1
0,8
0,6
0,4
0,2
0
1
Executie tijd per iteratie
(sec)
Executietijd afhankelijk van aantal iteraties
(rooster grootte 40x40x40)
Aantal iteraties
Figuur 10.Gemiddelde
executietijd per iteratie.
De eerste iteratie duurt het langst. Dat geldt zowel voor Java als voor C++. Nadat alle functies
en data in het geheugen zijn geladen gaat het rekenen in volgende iteraties sneller. Op de
linker grafiek (figuur 10) is Java-implementatie aanvankelijk trager in vergelijking met C++.
Door de optimalisaties van Java Virtual Machine is de Java implementatie uiteindelijk sneller
dan C++. Op de rechter grafiek is de Java-applicatie vanaf het begin sneller. Dat komt doordat
het rooster groter is. Het is namelijk zo dat binnen de main-loop van de simulatie
verschillende functies worden aangeroepen. Deze functies moeten voor alle punten van het
rooster bepaalde berekeningen uitvoeren. Hoe meer punten er zijn hoe meer van dezelfde
berekeningen moet uitgevoerd worden. De metingen tonen aan dat door betere optimalisatie
van deze routines heeft de Java applicatie betere performance.
Deze performance wordt bereikt dankzij Java Just-In-Time compiler. Door gebruik te maken
van JIT-compiler kan een Java applicatie enorm verbeterd worden[11]. Om de invloed van de
JIT-compiler te demonstreren wordt hetzelfde experiment(figuur 10, links) nog een keer
uitgevoerd. Maar deze keer wordt JIT-compiler uitgeschakeld. Het resultaat is op de figuur 11
te zien. Zoals men kan verwachten is de Java applicatie zonder JIT vele malen trager dan C++.
De performance van een Java applicatie wordt dus dramatisch beïnvloed door het gebruik van
JIT-compiler.
12
12
Java
10
8
C++
6
4
Java zonder
JIT
2
Figuur 11. Performance van
de applicatie zonder
JIT-compiler
30
15
5
3
0
1
Executie tijd per iteratie
(sec)
Executietijd afhankelijk van aantal iteraties
(rooster grootte 40x40x40)
Aantal iteraties
De rekensnelheid is dus de oorzak van het verschil in de performance tussen de twee
implementaties. Door betere optimalisaties presteert de Java-implementatie beter dan C++.
7.2 Performance metingen op meerdere clusters
In deze sectie analyseren we de speedup van de parallelle Java-applicatie. De speedup’s van
de simulatie op 1, 2 en 4 DAS2-clusters worden op de figuur 12 gepresenteerd.
Speedup van de Java im plem entatie
(roostergrootte 40x40x40)
Speedup van de Java im plem entatie
(roostergrootte 80x80x80)
1,4
1,2
Op 1 cluster
1
0,8
Op 2
clusters
0,6
0,4
Op 4
clusters
Speedup
Speedup
1,8
1,6
0,2
0
5
4,5
4
3,5
3
2,5
2
1,5
1
0,5
0
Op 1 cluster
Op 2
clusters
Op 4
clusters
1 2 4 8 12 18 24 36
1 2 4 8 12 18 24 36
Aantal processors
Aantal processors
Speedup
Speedup van de Java-implementatie
(roostergrootte 120x120x120)
9
8
7
6
5
4
3
2
1
0
Op 1 cluster
Op 2 clusters
Op 4 clusters
1
2
4
8
12
16
24
36
Aantal processors
13
Figuur 12. Speedup van de
Jama-implementatie op
meerdere clusters.
Theoretisch moet de performance van de parallelle applicatie die verdeeld is over een aantal
clusters iets lager zijn dan van de applicatie op één cluster. De communicatie tussen de nodes
van verschillende clusters verloopt namelijk iets trager dan tussen de nodes binnen één cluster.
We zien echter dat de speedup’s op alle grafieken nauwelijks van elkaar afwijken. Alleen op
de laatste grafiek(bij de roostergrootte van 120x120x120) is er een sprake van een klein
verschil. Daarvoor zijn er twee mogelijke verklaringen.
De eerste is het aantal processors die buiten de cluster met elkaar communiceren. In het geval
van 2 clusters zijn dat er twee. Alle processors worden namelijk in twee groepen
verdeeld( een groep op elke cluster). De twee processors op de “randen” van de groep
communiceren met processors buiten de cluster. Neem bijvoorbeeld een groep van processors
zoals op figuur 2. Alleen processors 0 en 2 zouden dan met processors op een andere cluster
communiceren. Omdat dezelfde processors tegelijkertijd met een van de processors binnen de
cluster communiceren kunnen we zeggen dat de hoeveelheid externe communicatie in totaal
gelijk is aan de communicatie van één processor. Dus voor twee clusters zijn er twee
processors die data oversturen naar een andere cluster. Voor vier clusters zijn er
respectievelijk vier processors. Dat aantal is kennelijk niet groot genoeg om de performance
sterk te beïnvloeden vooral als er meerdere processors aan de berekening meedoen. Maar het
tweede aspect van de communicatie tussen de clusters is veel belangrijker.
De tweede verklaring voor deze resultaten is de hoeveelheid data die er overgestuurd wordt.
De volgende staafdiagrammen (figuur 13) representeren de totale communicatietijd van de
simulatie.
Communicatietijd (sec)
Totale communicatietijd over 50
iteraties
12
10
8
1 cluster
6
2 clusters
4
2
4 clusters
Figuur 13. De totale
communicatietijd van de
simulatie op meerdere
clusters.
0
40
80
120
Roostergrootte
De verschillen zijn het best te zien bij de roostergrootte van 1203 . Er moeten meer punten
overgestuurd worden dus duurt de communicatie tussen de clusters wat langer. Het grootste
verschil (tussen 1 cluster en 4 clusters) is minder dan 1 seconde. Dus het is niet meer dan 0,02
sec. per iteratie. Op deze manier is de invloed van de communicatietijd op de algemene
performance van de applicatie helemaal niet zo groot. Daarom verschillen de speedup’s niet
zo veel van elkaar. Vooral bij het grote rooster is het verschil duidelijker te zien. Dus voor de
groottere roosters zou de communicatietijd tussen de clusters wel van groot belang zijn voor
de performance van de applicatie op meerdere clusters.
14
8. Conclusie en Discussie
De resultaten van dit onderzoek tonen aan dat de Java implementatie van Lattice Boltzmann
Method betere performance heeft dan C++ implementatie. De Java JIT-compiler speelt
daarbij de belangrijkste rol. De parallelle Java applicatie was geschreven met behulp van GMI.
Ondanks iets tragere communicatie in vergelijking met MPI biedt GMI veel mogelijkheden
voor het schrijven van efficiënte parallelle applicaties in Java. Er kunnen alle mogelijke
communicatie schema’s met GMI worden geïmplementeerd. Doordat de gebruiker zelf
communicatie methods kan definiëren is GMI veel flexibeler dan MPI met voorgedefinieerde
missage passing routines. De parallellisatie van de Java code met behulp van GMI resulteert
dus in een efficiënte parallelle Java applicatie.
Java is in de laatste jaren enorm vooruit gegaan. Helaas zijn er niet veel recente
wetenschappelijke artikels over de performance van Java ten opzichte van C of C++. In de
ogen van vele mensen is Java nog steeds een trage en inefficiënte programmeer omgeving.
Maar het is blijkbaar nog een grote vraag of dat inderdaad zo is. In dit werk is aangetoond dat
het niet altijd het geval hoeft te zijn.
We kunnen concluderen dat Java in combinatie met Ibis en GMI uitermate geschikt is voor de
parallelle wetenschappelijke applicaties zoals Lattice Boltzmann simulatie. Dat zou ook
gelden voor vele andere wetenschappelijke applicaties. Maar daarnaar zou nog meer
onderzoek gedaan moeten worden.
Dankwoord
Tot slot wil ik de mensen die mij bij dit project hebben geholpen hartelijk bedanken:
Alfons Hoekstra voor het begeleiden tijdens het project.
Jason Maassen voor de hulp met Ibis en GMI.
Het docententeam: Inge Bethke, Dick van Albada, Rein van den Boomgaard voor de
goede adviezen en steun.
Referenties
[1]. NINJA: Java for High Performance Numerical Computing
Jos´ e E. Moreira, Samuel P. Midkiff, Manish Gupta, Peng Wu, George Almasi
IBM Thomas J. Watson Research Center
Yorktown Heights,
[2]. Rob V. van Nieuwpoort, Jason Maassen, Gosia Wrzesinska, Rutger Hofman, Ceriel
Jacobs, Thilo Kielmann, Henri E. Bal:
Ibis: a Flexible and Efficient Java-based Grid Programming Environment,
Accepted for publication in Concurrency & Computation: Practice & Experience Vol. 17, No.
7-8, pp. 1079-1107, 2005.
[3]. He, X. & Luo, L. (1997). Theory of the lattice Boltzmann method: from the Boltzmann
equation to the lattice Boltzmann equation. Phys. Rev. E 56, 6811.
[4]. Kandhai, D., Koponen, A., Hoekstra, A. G., Kataja, M., Timonen, J. & Sloot, P. M. A.
(1998). Lattice-Boltzmann hydrodynamics on parallel systems. Computer Phyics
Communications. Year: 98 vol: 111 issue: 1-3 page: 14
15
[5]. Distributed Cellular Automata: Large Scale Simulation of Natural Phenomena
P.M.A. Sloot, J.A. Kaandorp, A.G. Hoekstra and B.J. Overeinder , in Zomaya, Ercal, Olariu
(Eds.) Solutions to Parallel and Distributed Computing Problems, Lessons from Biological
Sicences, chapter 1 (John Wiley & Sons, New York), 2001.
[6]. Lattice-Boltzmann hydrodynamics on parallel systems. D. Kandhai, A. Koponen, A.G.
Hoekstra, M. Kataja, J. Timonen. Computer Physics Communications 11(1998) 14-26
[7]. Academisch Proefschrift
“Method Invocation Based Communication Models for Parallel Programming in Java” by
Jason Maassen
[8]. K. Yelick, L. Semenzato, G. Pike, C. Miyamoto, B. Liblit, A. Krishnamurthy, P. Hilfinger,
S. Graham, D. Gay, P.Colella and A. Aiken. Titanium: A high=performance Java dialect. In
Proc. of the ACM 1998 Workshop on Java for High-Performance Network Computing. ACM
press, 1998
[9] M.Philipsen, B. Haumacher and C. NesterMore efficient serialization and RMI for Java.
Concurrency: Practice and Experience, 12(7):495-518, May 2000
[10]. R.R.Raje, J.I. William and M.Boyles. Asynchronous Remote Method Invocation (ARMI)
Mechanism for Java. Concurrency: Practice and Experience, 9(11):1207-1211, November
1997.
[11]. T. Suganuma, T. Ogasawara, M. Takeuchi, T. Yasue, M. Kawahito, K. Ishizaki, H.
Komatsu, and T. Nakatani “Overview of the IBM Java Just-in-Time Compiler” IBM systems
journal vol.39number 1, 2000 “Java performance”
[15]. Stephen Wolfram Cellular automata and complexity: Collected Papers
Publisher: Addison-Wesley, 1994 ISBN: 0201627167
[14].Cellular Automata Machines: A New Environment for Modeling (Scientific Computation)
by: Tommaso Toffoli, Norman Margolus EAN: 9780262200608 ISBN: 0262200600
Publication date: April 22, 1987 Publisher:The MIT Press
[12] .Numerical Analysis and Scientific Computation
by: Jeffery J. Leader EAN: 9780201734997, ISBN 0201734990 Publication date: February
05, 2004 Publisher: Addison Wesley
[13]. Fundamentals of Computational Fluid Dynamics (Scientific Computation)
by: H. Lomax, Thomas H. Pulliam, David W. Zingg EAN: 9783540416074 ISBN:
3540416072 Publication date: March 22, 2004 Publisher: Springer
[16]. The Lattice Boltzmann Equation for Fluid Dynamics and Beyond (Numerical
Mathematics and Scientific Computation)
by: S. Succi, Sauro Succi EAN: 9780198503989, ISBN: 0198503989 Publication date:
August 01, 2001, Publisher: Oxford University Press
[17]. Java Grande Forum, http://www.javagrande.org/
16
Download