190 likes | 344 Views
Föreläsning 6 - 29.10.2010 Innehåll : Att designa parallella program - manuell vs. automatisk parallellisering - Java och ” multi-core ” processorer Hur skall koden parallelliseras ?. PROCESSPROGRAMMERING. Manuell vs. automatisk parallellisering.
E N D
Föreläsning 6 - 29.10.2010 Innehåll: Attdesignaparallellaprogram - manuell vs. automatiskparallellisering - Java och ”multi-core” processorer Hurskallkodenparallelliseras? PROCESSPROGRAMMERING
Manuell vs. automatisk parallellisering Att designa parallella program har länge varit en manuell process Att designa parallell kod är komplext och ger ofta upphov till oväntade fel (trådsäkerhet) Det finns en mängd olika verktyg för automatisk parallellisering av program (främst för Fortran och varianter av C) Parallelliseringsverktyg tillåter ofta två olika typer av automatisering: Fullt automatisk Programmeraren ger direktiv för parallellisering för kompilatorn
Manuell vs. automatisk parallellisering Ett exempelpå en parallelliserings-APIärOpenMP, se http://openmp.org/wp/ Det harocksåutvecklatsliknandeverktyg för Java, t.ex. JOMP: http://www2.epcc.ed.ac.uk/computing/research_activities/jomp/index_1.html GroovyParallel: http://gpars.codehaus.org/ Ateji: http://www.ateji.com/ Automatiskparallelliseringärofta en bralösningmen det finnsocksåproblem: Felaktigaresultatkanproduceras Mindreflexibeltänmanuellparallellisering Begränsarsejtill en viss del av parallelliserbarkod, främstloopar
Manuell vs. automatisk parallellisering ”Ordentliga” automatiska parallelliseringsverktyg för Java saknas? Vi kommer tillsvidare att koncentrera oss på manuell parallellisering eftersom detta ger en bättre förståelse för hur Java program kan parallelliseras och optimeras för Multi- processor arkitekturer
Java och ”multi-core” processorer Dagens Java virtualmaskinerklarar av attanvändamulti-coreprocessorer Multipla Java trådarklarar av attexekverasparallelltpåmultipla processoreromsådanafinns. ConcurrentAPI:nsomfunnitsmedsedan JDK5 har (därbl.a. ThreadPoolsdefinieras) bästastödet för multi-coreprocessorer
Hur parallellisera? Hur skall vi då parallellisera ett java program på rätt sätt för att få bästa möjliga prestanda? T.ex. Om vi har en seriell kod (ickeparallelliserad) måste vi söka fram sådana algoritmer som är ”tunga” (detta kan göras manuellt men det finns även ”performance analysis” verktyg som man kan använda för detta ändamål) Den enklaste typen av parallelliserbar kod är loopar En lång loop som t.ex. utför en beräkning för varje iterationsvarv och där varje iterationsvarv är oberoende av varandra kan enkelt splittas upp i två eller flera delar (Denna typ av parallellisering brukar kallas för ”embarrassingly parallell” eftersom det är så enkelt, bl.a. ingen kommunikation behövs mellan de olika delarna)
Hur parallellisera? Det mest optimala är att splitta upp loopen i så många delar som det finns tillgängliga processorer/processorkärnor Att splitta upp en loop i flera delar än antalet processorer/processorkärnor gör inte koden längre effektivare (eftersom processorerna i stället börjar alternera mellan de olika ”överlopps” trådarna) Antalet lediga processorkärnor kan i ett Java-programm fås fram på följande sätt: Runtime.getRuntime().availableProcessors();
Hur parallellisera? Närmansplittarupp en loop i t.ex. tvådelargörman det i praktikensåatt vi har en s.k. ”masterthread” ochtvås.k. ”workerthreads” Masterthreadsköteromattskapa en trådgrupppåtvåtrådarochdelegerarsedan uppgifteråt ”worker” trådarna Sålänge ”worker” trådarna ”arbetar” väntarmastertråden (medget())
Hur mycket effektivare program får vi? I teorin borde en loop försnabbas med 50% om vi har två processorkärnor och fördelar ”arbetet” jämnt mellan båda kärnorna. Detta stämmer dock ej i praktiken eftersom: Att skapa trådar/överföra kod till trådgrupper tar processortid Båda processorkärnorna är sällan (nästan aldrig) helt och hållet lediga
Amdahl’s lag Den potentiella effektiveringen av ett program definieras i följande formel: 1 ----------------------------- Speed up = P + S --- N P = Hur stor del av koden som kan parallelliseras (0 = ingen alls, 1 = all kod) N = Antelet processorer/processoerkärnor S = Hur stor del av koden som är seriell (0 = ingen alls, 1 = all kod) I praktiken uppnår vi aldrig speedup=2 (dubbelt snabbare) eftersom 100% av koden (P=1) kan aldrig i praktiken parallellisera, vi måstju ju bl.a. skapa en trådgrupp, föra över uppgifter til trådarna osv.
Förståproblemetochprogrammet Innan du börjar slösa tid på att parallellisera, kontrollera om ett visst problem kan parallelliseras eller inte Exempel på problem som kan parallelliseras: Avläs 1 miljon mätvärden på temperaturer ur en väderstations logg Beräkna medeltemperaturen på basen av alla mätvärden Exempel på problem som INTE kan parallelliseras: Beräkning av en Fibonacci-serie (en tabell där ett element är summan av de två föregående elementen)
Förståproblemetochprogrammet Hitta ”hotspots” i programmet Var i koden spenderar programmet mest tid? Detta kan göras i Netbeans genom att t.ex. Använda ”Profiler” verktyget Fokusera dej på att parallelisera ”hoptspottarna” och undvik att parallellisera den delen av koden som inte förbrukar mycket processortid Identifiera ”flaskhalsar” i programmet Finns det delar av koden som är extremt långsamma eller som förorsakar att parallelliserbara delar av programmet stannar upp, t.ex. p.g.a I/O Konstruera programmet så att långsamma delar av koden inte förhindrar parallelliseringen
Partitionering av koden En av de första stegen vid parallellisering är att bryta upp ett problem i diskreta ”bitar” som kan exekveras parallellt Finns två grundläggande sätt att partitionera: Domain decomposition Functional decomposition
”Domain decomposition” Man delar upp en mängd data i flera delar och utför sedan samma operation på de olika datadelarna parallellt Ett exempel på där denna metod kan tillämpas är inläsning av mätdata från väderdatabasen (se slide nr 12)
”Functional Decomposition” I detta fall spjälker man upp själva själva operationen som skall utföras på någon typ av data i flera delar Problemet delas upp enligt det arbete som ska utföras Sedan uttförs varje ”deluppgift” parallellt på samma data
”Functional Decomposition” Exempel på problem där ”Functional Decomposition” kan tillämpas: Signalprocessering:
Kommunikation mellan ”uppgifter” Behovet av kommunikation mellan trådarna som utför de olika parallella uppgifterna beror helt på problemet: Kommunikation behövs INTE: Vissa typer av problem kan bli partitionerade och exekverade parallellt utan att det finns behov för utybe av data mellan trådarna T.ex. Analysering av mätdata
Kommunikation mellan ”uppgifter” Kommunikation BEHÖVS: De flesta typer av problem är inte så lätta att parallellisera som ovannämnda exempel Ofta behöver en uppgift uttyba någon typ av data med en annan process T.ex. vid parallellisering av en funktion som beräknar värmespridning
Kommunikation mellan ”uppgifter” Det är viktigt att ta i beaktande vissa saker om kommunikation mellan ”upptifter” behövs till följd av parallellisering: Vad är kostnaden? Behövs synkronisering? => leder till blockering och förlångsammar parallelliseringen. Lönar det sej ändå att parallellisera trots att parallellisering förorsakar ”extra” kostnader och problem?