INF2440 Uke 9, v2017 : Om Oblig 3 - radixsortering, Ulike Threadpools, JIT-kompilering. Arne Maus PSE, Inst. for informatikk

Like dokumenter
INF2440 Uke 8, v2016 : Om Oblig 3 - radixsortering, Ulike Threadpools, JIT-kompilering. Arne Maus PSE, Inst. for informatikk

7) Radix-sortering sekvensielt kode og effekten av cache

INF2440 Uke 8, v2015 : Om Oblig 3, Ulike Threadpools, JIT-kompilering. Arne Maus PSE, Inst. for informatikk

INF2440, Uke 3, våren2015 Regler for parallelle programmer, mer om cache og Radix-algoritmen. Arne Maus OMS, Inst. for informatikk

INF2440 Uke 4, våren2014 Avsluttende om matrisemultiplikasjon og The Java Memory Model + bedre forklaring Radix. Arne Maus OMS, Inst.

INF2440, Uke 3, våren2014 Regler for parallelle programmer, mer om cache og Radix-algoritmen. Arne Maus OMS, Inst. for informatikk

UNIVERSITETET I OSLO

INF2440 Uke 12, v2014. Arne Maus OMS, Inst. for informatikk

INF2440 Uke 4, v2017 Om å samle parallelle svar, matrisemultiplikasjon og The Java Memory Model + evt bedre forklaring Radix

INF2440 Uke 4, v2015 Om å samle parallelle svar, matrisemultiplikasjon og The Java Memory Model + evt bedre forklaring Radix

INF2220 høsten 2017, 12. okt.

INF2440 Prøveeksamen, løsningsforslag, 20 mai Arne Maus PSE, Inst. for informatikk

INF2440 Uke 11, v2014 om parallell debugging og Goldbachs problem, om Oblig 3. Arne Maus OMS, Inst. for informatikk

INF3030, Uke 3, våren 2019 Regler for parallelle programmer, mer om cache og Matrise-multiplikasjon. Arne Maus / Eric Jul PSE, Inst.

UNIVERSITETET I OSLO

INF2440 Uke 6, våren2014 Mer om oppdeling av et problem for parallellisering, mye om primtall + thread-safe. Arne Maus OMS, Inst.

INF2440 Uke 10, v2018 : Arne Maus PSE, Inst. for informatikk

INF2440 Eksamen 2016 løsningsforslag. Arne Maus, PSE ifi, UiO

Prøveeksamen INF2440 v Arne Maus PSE, Inst. for informatikk

I et Java-program må programmøren lage og starte hver tråd som programmet bruker. Er dette korrekt? Velg ett alternativ

UNIVERSITETET I OSLO

INF2440 Uke 7, våren2017. Arne Maus PSE, Inst. for informatikk

UNIVERSITETET I OSLO

INF2440 Uke 5, våren2015 Om oppdeling av et problem for parallellisering, mye om primtall + thread-safe. Arne Maus PSE, Inst.

UNIVERSITETET I OSLO

Parallellprogrammering og Sortering INF nov. 2015

Arne Maus OMS, Inst. for informatikk

INF2440 Uke 8, v2017. Arne Maus PSE, Inst. for informatikk

INF NOV PARALLELL SORTERING. Arne Maus, PSE, Ifi

INF2440 Uke 7, våren2015. Arne Maus PSE, Inst. for informatikk

INF2440 Uke 11, v2017 om Goldbachs problem og Oblig 2,3. Arne Maus PSE, Inst. for informatikk

INF2440 Uke 9, v2014 : Arne Maus OMS, Inst. for informatikk

INF2220 høsten 2016, 9. nov.

UNIVERSITETET I OSLO

INF2440 Uke 13, v2015. Arne Maus PSE, Inst. for informatikk

Fig1. Den konvekse innhyllinga av 100 tilfeldige punkter i planet (de samme som nyttes i oppgaven.)

INF2440 Uke 11, v2015 om parallell debugging og Goldbachs problem, om Oblig 2,3 og 4. Arne Maus PSE, Inst. for informatikk

INF2220 høsten 2015, 5. nov.

INF2220 høsten 2017, 19. okt.

INF2440 Effektiv parallellprogrammering Uke 2 -, våren tidtaking. Arne Maus PSE, Inst. for informatikk

INF2440 Uke 9, v2015 : Arne Maus PSE, Inst. for informatikk

INF2440 Uke 10, v2017 : Arne Maus PSE, Inst. for informatikk

Kap 19. Mer om parallelle programmer i Java og Kvikksort

INF2440 Uke 5, våren2016. Arne Maus PSE, Inst. for informatikk

INF2440 Uke 10, v2014 : Arne Maus OMS, Inst. for informatikk

INF2440 Uke 5, våren2017. Arne Maus PSE, Inst. for informatikk

Løsnings forslag i java In115, Våren 1996

INF2440 Uke 10, v2015 : Arne Maus PSE, Inst. for informatikk

IN3030 Uke 12, v2019. Eric Jul PSE, Inst. for informatikk

INF1000 : Forelesning 4

INF2440 Uke 10, v2016 : Arne Maus PSE, Inst. for informatikk

INF2220: Time 12 - Sortering

i=0 i=1 Repetisjon: nesting av løkker INF1000 : Forelesning 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker j=0 j=1 j=2 j=3 j=4

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

Løsningsforslag ukeoppg. 6: 28. sep - 4. okt (INF Høst 2011)

INF2440 Uke 14, v2015. Arne Maus PSE, Inst. for informatikk

INF2440 Uke 15, v2014 oppsummering. Arne Maus OMS, Inst. for informatikk

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

INF2440 Uke 15, v2015 oppsummering. Arne Maus PSE, Inst. for informatikk

Sortering med tråder - Quicksort

UNIVERSITETET I OSLO

INF2440 Uke 15, v2017 litt om parallellisering av Oblig4 + oppsummering av kurset. Arne Maus PSE, Inst. for informatikk

INF 1000 høsten 2011 Uke september

MER OM PARALLELLE PROGRAMMER I JAVA OG KVIKKSORT

INF2440 Uke 13, v2014. Arne Maus OMS, Inst. for informatikk

INF1000 undervisningen INF 1000 høsten 2011 Uke september

INF Uke 10. Ukesoppgaver oktober 2012

INF2440 Uke 11, v2016 om Goldbachs problem og Oblig 2,3. Arne Maus PSE, Inst. for informatikk

Tråder Repetisjon. 9. og 13. mai Tråder

INF Notater. Veronika Heimsbakk 10. juni 2012

INF2440 Effektiv parallellprogrammering Uke 1, våren Arne Maus PSE, Inst. for informatikk

Forelesning inf Java 5

INF2220: Forelesning 1. Praktisk informasjon Analyse av algoritmer (kapittel 2) (Binær)trær (kapittel )

INF1000: noen avsluttende ord

Forelesning inf Java 5

Løsningsforslag for Obligatorisk Oppgave 2. Algoritmer og Datastrukturer ITF20006

Uke 8 Eksamenseksempler + Ilan Villanger om studiestrategier. 11. okt Siri Moe Jensen Inst. for informatikk, UiO

UNIVERSITETET I OSLO

INF1010 Tråder II 6. april 2016

INF2440 Effektiv parallellprogrammering Uke 1, våren Arne Maus PSE, Inst. for informatikk

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister

Java PRP brukermanual

Kap 2: Løkker og lister

Oversikt. INF1000 Uke 1 time 2. Repetisjon - Introduksjon. Repetisjon - Program

Forkurs INF1010. Dag 2. Andreas Færøvig Olsen Tuva Kristine Thoresen

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Kort repetisjon av doble (nestede) løkker Mer om 1D-arrayer Introduksjon til 2D-arrayer Metoder

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister Videre

Norsk informatikkolympiade runde

Liste som abstrakt konsept/datatype

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

UNIVERSITETET I OSLO

INF1010, 22. mai Prøveeksamen (Eksamen 12. juni 2012) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

INF1000 (Uke 5) Mer om løkker, arrayer og metoder

INF1000: Forelesning 7

Forkurs INF1010. Dag 2. Andreas Færøvig Olsen Gard Inge Rosvold Institutt for Informatikk, 14.

Transkript:

INF Uke 9, v7 : Om Oblig - radixsortering, Ulike Threadpools, JIT-kompilering Arne Maus PSE, Inst. for informatikk

Om inf våren 7 Ingen undervisning (forelesning eller gruppetimer i påsken (. 7. april). Obliger: Oblig (primtallsfaktorisering) leveres. mars Oblig (RadixMulti) lagt ut. mars og leveres 7.april Oblig (konveks innhylling) legges ut 7. april og leveres. mai

Hva så vi på i uke 8 Et sitat om tidsforbruk ved faktorisering Om en feil i Java ved tidtaking (tid ==??) Hvordan parallellisere rekursive algoritmer Gå IKKE i direkte oversettelses-fella eksemplifisert ved Quick-sort, ulike løsninger, håpløse Hvor lang tid tar de ulike mekanismene i Java og 8 Store forbedringer Java til Java8

Hva skal vi se på i uke 9:. Om oblig generell Radix-sortering (MultiRadix) Dette er en variant av Radix-sortering som automatisk prøver å finne ut hvor mange sifre den skal sortere på ut fra verdien av max. (- sifre) og kaller Radix-metoden tilsvarende antall ganger. Meget rask. Dere får sekvensiell versjon, skal parallelliser denne, skrive rapport osv. Et mer detaljert gjennomgang av steg b). En effektiv Threadpool? Executors.newFixedThreadPool. FinnMax / et enkelt problem og JIT/kompilering. Mer om effektivitet og JIT-kompilering!. Om problem(?) mellom long og int

Oblig lagt ut på fredag. mars Parallelliser Radix-sortering med et variabelt antall sifre (MultiRadix) Bytter om på array-pekere for at den mest sorterte arrayen alltid er i det som pekes på av int [] a. Kopierer alt til den arrayen som ble brukt i kallet hvis odde antall sifre brukes i sorteringa. Skriv rapport om speedup for n=,,, mill., mill og mill. MultiRadix består av to metoder, begge skal parallelliseres (men ikke en evt. array-kopiering på slutten av første metode). Den første, finn max(a[]) løst tidligere Den andre har tre steg løses i parallell effektivt: a) tell hvor mange det er av hvert sifferverdi i a[] i count[] b) legg sammen verdiene i count[] til pekere til b[] c) flytt tallene fra a[] til b[] sortert på siffer i. Steg b) gitt i ukeoppgave 8/9 (hvor bla. hver tråd har sin kopi av count[])

Oblig) Radix-sortering sekvensielt & litt parallelt kode og effekten av cache + Dels er denne gjennomgangen av vanlig Radix-sortering viktig for å forstå en senere parallell versjon. Dels viser den effekten vi akkurat så tilfeldig oppslag i lageret med korte eller lange arrayer b[] i uttrykk som a[b[i]] kan gi uventede kjøretider. Ideen bak Radix er å sortere tall etter de ulike sifrene de består av og flytte de frem og tilbake mellom to arrayer a[] og b[] slik at de stadig blir sortert på ett siffer mer. I multiradix varierer (øker vi) antall sifre vi sorterer med at etter hvor mange bit det er i max-tallet i a[]

Den første av to algoritmer som MultiRadix består av. int [] radixmulti(int [] a) { long tt = System.nanoTime(); // - digit radixsort of : a[] int max = a[], numbit =, numdigits, n =a.length; int [] bit ; // a) finn max verdi i a[] for (int i = ; i < n ; i++) if (a[i] > max) max = a[i]; while (max >= (L<<numBit) )numbit++; // antall bit i max radixmulti // bestem antall bit i numbits sifre numdigits = Math.max(, numbit/num_bit); // NUM_BIT =, 7, 8 eller 9 bit = new int [numdigits]; int rest = numbit%numdigits, sum =;; radixsort radixsort // fordel resten av bitene vi skal sortere paa jevnt for (int i = ; i < bit.length; i++){ bit[i] = numbit/numdigits; if ( rest-- >) bit[i]++; } int[] t, b = new int [n]; // (forts) 7

for (int i =; i < bit.length; i++) { radixsort( a,b,bit[i], sum); // i-te siffer fra a[] til b[] sum += bit[i]; // bytt om arrayer (bare pekere) t = a; a = b; b = t; } if (bit.length%!= ) { // et odde antall sifre, kopier innhold tilbake til original a[] (som nå er b) System.arraycopy (a,,b,,a.length); } double tid = (System.nanoTime() -tt)/.; System.out.println("\nSorterte "+n+" tall paa:" + tid + "millisek."); testsort(a); return a; } // end radix void testsort(int [] a){ for (int i = ; i< a.length-;i++) { if (a[i] > a[i+]){ System.out.println("SorteringsFEIL på plass: "+i + " a["+i+"]:"+a[i]+" > a["+ (i+)+"]:"+a[i+]); return; } } }// end enkel sorteringstest 8

radixmulti radixsort radixsort /** Sort a[] on one digit ; number of bits = masklen, shiftet up shift bits */ static void radixsort ( int [] a, int [] b, int masklen, int shift){ int acumval =, j, n = a.length; int mask = (<<masklen) -; int [] count = new int [mask+]; // b) count=the frequency of each radix value in a for (int i = ; i < n; i++) count[(a[i]>>shift) & mask]++; // c) Add up in 'count' - accumulated values for (int i = ; i <= mask; i++) { j = count[i]; count[i] = acumval; acumval += j; } // d) move numbers in sorted order a to b for (int i = ; i < n; i++) b[count[(a[i]>>shift) & mask]++] = a[i]; }// end radixsort 9

Om høyre, minst signifikant siffer først Radix Radix-sortering, fast eller variablet antall sifre: R: Radix-sortering med ett siffer R: Radix-sortering med to sifre R: Radix-sortering med tre sifre MultiRadix variabelt antall Alle består av to metoder: radix,radix, radix multiradix som: Først regner ut max-verdien i a[]. Så regnes ut noen konstanter som antall bit i det/de sifrene a[] skal sorteres med. Deretter kalles metoden radixsort for hvert siffer det skal sorteres etter radixm radix radix radix radixsort radixsort radixsort radixsort radixsort radixsort radixsort radixsort

a count... m - Figure. The use of array count in any radix algorithm when sorting on a digit with numbit bits. The illustration is after sorting. We see that there are two elements in a[] with the value on that digit, elements with value,,and element with value numbit -.

Forklaring av: count[(a[i]>> shift) & mask]++; del Tar det innenfra og ut; a[i]>> shift Ethvert ord i lageret består a -ere og -ere (alt er binært) Java har flere skift-operasjoner feks.: a[i]>>b betyr: skift alle bit-ene i a[i] b antall plasser til høyre og fyll på med b stk -er på venstre del av a[i]. a[i]<<b betyr: skift alle bitene i a[i] b antall plasser til venstre og fyll på med b stk -er på høyre del av a[i]. De bit-ene som skiftes ut av a[i] går tapt i begge tilfeller. a<< er det samme som a*, a<< er det samme som a*, a<<k er det samme som a* k Ett element i a[]: bit masklen shift mask = masklen ere

Forklaring av: count[(a[i]>> shift) & mask]++; del Java har flere bit-logiske operasjoner, for eksempel & (og): a & b er et tall som har -ere der både a og b har en -ere, og resten er. Eks: a& = et tall som er null over alt unntatt i bit som har samme bit-verdi som bit i a. Vi kan betrakte b som en maske som plukker ut de bitverdiene i a hvor b har -ere. Poenget er at: (a[i]>> shift) & mask er raskeste måte å finne hvilken verdi a[] har for et gitt siffer (sifferverdien) : Først skifter vi bit-ene i a[i] ned slik at sifferet vi er interessert i ligger helt nederst til høyre. Så &-er vi med en maske som bare har -ere for så mange bit vi har i det sifferet vi er interessert i nederst (og ellers). count[(a[i]>> shift) & mask] er da det elementet i count[] som har samme indeks som sifferverdien i a[i]. Det elementet i count[] øker vi så med (++ operasjonen)

Eksempel (shift = og mask =7) vi vil ha dre siffer a[i] = 7 (i 8-tallsystemet)=.. a[i] >> =.. (a[i] >>) &.. =.. = Vi kan velge fritt hvor lange (antall bit) sifre og hvor mange sifre vi vil ha sortere på, men summen av antall bit i sifrene vi sorterer på må være større eller lik antall bit i max, det største tallet i a[]. Et godt valg er å ha en øvre grense på bit-lengden av et siffer f.eks =, og da heller ta så mange sifre det trengs for å sortere a[].

Stegene i en radix-sortering radix,, eller MultiRadix: Finn maks verdi i a[] og bestem antall sifre med mer. FinnMax har vi parallellisert radixsort (en gang for hvert siffer): a) Tell opp hvor mange det er i a[] med de ulike mulige sifferverdiene på dette sifferet. b) Adder sammen verdiene til en array som sier hvor vi skal flytte et element i a[] med en gitt sifferverdi. c) Flytt elementene fra a[] til b[] slik at de minste verdier kommer øverst,..osv d) Kopier b[] tilbake til a[] (trenges ikke i radix,radix,..) Stegene a, b og c skal vi senere parallellisere (d kan fjernes)

Derfor MultiRadix &Hva viser dette om cachen? manglende caching av data for Radix gir lengere kjøretider Radix med ganger så lang kode som Radix går jevnt over - ganger så fort når n>! Radixmed ganger så lang kode som Radix går ganger så fort når n > mill.

Eksempel den sekvensielle algoritmen Vi aksepterer at vi forrige gang greide å finne verdien av et siffer i a[]: (a[i]>> shift) & mask regner ut sifferverdien av et siffer i a[i] som : Har ett eller flere sifre til høyre for seg (mindre signifikante) som til sammen i sum har shift bit Mask inneholder så mange -ere nederst som det er bit i det sifferet vi vil finne nå og er ellers. Anta at vi skal sortere denne a[] på to sifre, a 7 7 7

Høyre, minst signifikant siffer først sortering på to sifre: Radix som vi nå bruker Radix-sortering, nå siffer: Radix: Radix-sortering på to sifre Radix bestås av to metoder: radix som først regner ut max-verdien i a[]. Så regnes ut noen konstanter, som antall bit i de to sifrene a[] skal sorteres med. Deretter kalles metoden radixsort for hvert av de to sifrene (dvs. to ganger) radix radixsort radixsort 8

Stegene i metoden: radixsort: a) Tell opp i en array count slik at count[k] = hvor mange ganger k er en sifferverdi a[]. Eks. hvor mange tall i a[] = i dette sifferet? b) Legg sammen antallene i count slik at count[k] sier hvor i b[] vi skal plassere første element i a[] vi finner med sifferverdien k c) Finn sifferverdien i a[k] og flytt a[k] til b[] der count[sifferverdien] sier a[k] skal være. Øk count[sifferverdien] med til neste plass i b[] 9

Radix-sortering steg a) første, bakerste siffer Vi skal sorterere på siste siffer med bit sifferlengde (tallene -7) a) Tell opp sifferverdier i count[]: a 7 7 7 Før telling: count 7 Etter telling: count

Radix-sortering steg b) finne ut hvor sifferverdien skal plasseres De a[i] ene som inneholder j hvor skal de flyttes sortert inn i b[]? - Hvor skal -erne stare å flyttes, -erne,.osv b) Adder opp sifferverdier i count[]: Før addering: Etter addering : count 7 7 count b Kan også sies sånn: Første null-er vi finner plasserer vi b[], første ener i b[] fordi det er stk null-ere og de må først. To-erne starter vi å plassere i b[] fordi stk null-ere og stk en-ere som må før to-erne,.osv.

Radix-sortering på det første (minst signifikante), mest høyre siffer a c) flytt a[k] til b[] der count[s] peker, hvor s= sifferverdien i a[k], øk count[s] med. 7 7 Før flytting 7 count Før flytting b Etter flytting b 7 7

Så sortering på siffer (det lengst til venstre) fra b[] til a[], trinn a) og b) b 7 7 Etter telling på siffer : 7 count Etter addering : count 7 a

Så sortering på siffer fra b[] til a[] trinn c) b 7 7 Etter telling på siffer : 7 count Etter addering : count 7 7 a 7

Situasjonen etter sortering fra b[] til a[] på siffer Etter flytting b 7 7 count 7 7 a 7 7 a[] er sortert!

Hvordan parallelliser vi MultiRadix? Fire steg som skal parallelliseres. multiradix: // a) find max verdi i a[]. radixsort: // b) count the frequency of each radix value in a. // c) add up in 'count' - accumulated values. // d) move numbers in sorted order a to b Vi skal nå se på én måte å parallelliser b) å telle de ulike sifferverdiene (jfr. Ukeoppgave 8/9)

Vi har altså bestemt hvilket siffer vi skal telle. Viktig : unngå konflikt om skriving (og lesing) ikke synkronisering. Her er oppskriften fra Ukeoppgave 8/9: 7

8 stegs oppskrift. Du kan godt prøve finne på noe enklere selv ) Alle trådene har synkronisert på den sykliske barrieren synk (de vet max fra multiradix). ) Opprett en to-dimensjonal int[][] allcount = new int[anttraader][] som fellesdata. I tillegg deklareres også int[]sumcount = new int[numsif] som fellesdata. ) Du deler så først opp a[] slik at tråd får de n/k første elementene i a[],tråd får de neste n/k elementene,, og tråd anttråder- de siste elementene i a[]. ) Hver tråd har en egen int[]count = new int[numsif]. Vi teller så i alle trådene opp hvor mange det er av hver mulig sifferverdi i den delen av a[] som vi har, og noterer det i vår lokale count[]. ) Når tråd i er ferdig med tellinga, henger den sin count[] opp i den doble int-arrayen som da vil inneholde alle opptellingene fra alle trådene, slik: allcount[i] = count; ) Alle trådene synkroniserer på den sykliske barrieren synk. ) Nå skal vi dele opp arrayen allcount[][] etter verdier i a[], slik at tråd får de n/k første elementene i sumcount[] og de n/k første kolonnene i allcount[][], tråd får de neste n/k elementene i sumcount[] og kolonnene i allcount[][],, osv. 7) Hver tråd i summerer så tallene i alle sine kolonner j fra allcount[..anttråder- ][j] til sumcount[j]. 8) Alle trådene synkroniserer på nytt på den sykliske barrieren synk. 8

) Opprett en to-dimensjonal int[][] allcount = new int[anttraader][] som fellesdata. I tillegg deklareres også int[]sumcount = new int[numsif] som fellesdata. (numsif = numbit, antall mulige sifferverdier i dette siffret) allcount anttraader - sumcount............. numsif- 9

) Du deler så først opp a[] slik at tråd får de n/k første elementene i a[],tråd får de neste n/k elementene,, og tråd anttråder- de siste elementene i a[]. ) Hver tråd har en egen int[]count = new int[numsif]. Vi teller så i alle trådene opp hvor mange det er av hver mulig sifferverdi i den delen av a[] som vi har, og noterer det i vår lokale count[]. a............. n - telles av tråd i I hver tråd i : count........ numsif-

) Når tråd i er ferdig med tellinga, henger den sin count[] opp i den doble intarrayen som da vil inneholde alle opptellingene fra alle trådene, slik: allcount[i] = count; ) Alle trådene synkroniserer på den sykliske barrieren synk. allcount anttraader - I tråd : count........ numsif- I tråd : count........ numsif-

7) Nå skal vi dele opp arrayen allcount[][] etter verdier i a[], slik at tråd får de n/k første elementene i sumcount[] og de n/k første kolonnene i allcount[][], tråd får de neste n/k elementene i sumcount[] og kolonnene i allcount[][],, osv. 8) Hver tråd i summerer så tallene i alle sine kolonner j fra allcount[..anttråder-][j] til sumcount[j]. 9) Alle trådene synkroniserer på nytt på den sykliske barrieren synk. allcount........ numsif- anttraader - Felles data: sumcount telles av tråd i........ numsif-

Gjenstår å parallelliser c) og b) Fire steg som skal parallelliseres. multiradix: // a) find max verdi i a[]. radixsort: // b) count the frequency of each radix value in a. // c) add up in 'count' - accumulated values. // d) move numbers in sorted order a to b c) Er vanskeligst i parallell

I) Om JIT-kompilering, finn Max-verdi i en array av 8 int, Modell-kode med tråd-pool Sekvensiell og parallell kjørt ganger M:\INFPara\FinnMax>java FinnM 8 8 Kjoering:, ant kjerner:8, anttraader:8 Max verdi parallell i a:788, paa:.7887 millisek. Max verdi sekvensiell i a:788, paa:.9 millisek. Kjoering:, ant kjerner:8, anttraader:8 Max verdi parallell i a:788, paa:.8 millisek. Max verdi sekvensiell i a:788, paa:.98 millisek. Kjoering:, ant kjerner:8, anttraader:8 Max verdi parallell i a:788, paa:.97 millisek. Max verdi sekvensiell i a:788, paa:.9 millisek. Median sequential time:.9, median parallel time:.8, n= 8, Speedup:., ant iterasjoner: Min sequential tid:.98ms, max sequential tid:.9ms Min parallell tid:.97ms, max parallell tid:.7887ms, n= 8, max/min sek:., n= 8, max/min para:.

) Om JIT-kompilering, finn Max-verdi i en array av 8 int, Modell-kode med tråd-pool, og iterasjoner edian sequential time:., median parallel time:.7, n= 8, Speedup:.8, ant iterasjoner: in sequential tid:.ms, max sequential tid:.ms in parallell tid:.978ms, max parallell tid:.89ms, n= 8, max/min sek:., n= 8, max/min para:. Median sequential time:.8, median parallel time:.7, n= 8, Speedup:., ant iterasjoner: Min sequential tid:.ms, max sequential tid:.98ms Min parallell tid:.8ms, max parallell tid:.9ms, n= 8, max/min sek:.8, n= 8, max/min para:. Median sequential time:., median parallel time:.7, n= 8, Speedup:.9, ant iterasjoner: Min sequential tid:.ms, max sequential tid:.8ms Min parallell tid:.77ms, max parallell tid:.ms, n= 8, max/min sek:., n= 8, max/min para: 9.7

Oppsummering JIT- Meget store hasthets-forbedringer av JIT-kompilering Speedup ikke mulig på små eksempler som n =8 Prøver vi f.eks n= 8mill får vi grei speedup (se nedenfor), men ikke med iterasjon Median sequential time:.7, median parallel time:.89, n= 8, Speedup:.7, ant iterasjoner: Min sequential tid:.8ms, max sequential tid:.99ms Min parallell tid:.9ms, max parallell tid:.9ms, n= 8, max/min sek:.7, n= 8, max/min para: 7.8 Hvorfor er forholdet max/min mindre her?

Oppsummering JIT- Meget store hasthets-forbedringer av JIT-kompilering Speedup ikke mulig på små eksempler som n =8 Prøver vi f.eks n= 8mill får vi grei speedup (se nedenfor), også nesten med ant. Iterasjoner = Median sequential time:.978ms, median parallel time:.9ms n= 8, Speedup:.9, ant iterasjoner: Min sequential tid:.77ms, max sequential tid:.88ms Min parallell tid:.9877ms, max parallell tid:.97ms, n= 8, max/min sek:., n= 8, max/min para:. Hvorfor er forholdet max/min nesten borte her? 7

II) En effektiv Threadpool? Vi har med modell-koden selv startet en samling av k tråder som- venter til vi vil kjøre ett problem (evt. flere ganger): enten med samme n for å få bedre tider (median) eller for en ny n. Ideen om å lage en samling av tråder som er klar for å løse neste oppgave har vi også i Java-biblioteket. Vi skal her se på: Executors.newFixedThreadPool i java.util.concurrent. Her kan vi også bytte ut problemet 8

Grunnidéene i Executors.newFixedThreadPool Du starter opp et fast antall tråder Hvis du under kjøring trenger flere tråder enn de startet må du vente til en av dem er ferdig og da er ledig For hver tråd som gjør noe er det tilknyttet et objekt av klassen Future: Den sier deg om tråden din er ferdig Du kan legge deg og vente på ett eller alle Future-objekter som join() med vanlige tråder Future-objektet bringer også med seg svaret fra tråd når den er ferdig, hvis den har noen returverdi En tråd som har terminert kan straks brukes på nytt fordi main-tråden venter ikke på tråden, men på tilhørende Future 9

For å administrere en slik mengde (pool) av tråder Må man først lage en pool (med tilhørende Vektor av Futures): class MinTraadpool{ MinTraadpool pt = new MinTraadpool (); int anttraader = Runtime.getRuntime().availableProcessors(); ExecutorService pool = Executors.newFixedThreadPool(pt.antTraader); List <Future> futures = new Vector <Future>(); Hvordan lage trådene og slippe dem ned i poolen (svømmebasenget): for (int j =; j < anttraader; j++) { Thread QParExec = new Thread(new FindExec(j)); futures.add(pool.submit(qparexec)); // submit starter trtåden }

For å administrere en slik mengde (pool) av tråder Slik venter man på framtider (Futures) get returnerer svaret (hvis noe ikke her) while (!futures.isempty()) { Future top = futures.remove(); try { if (top!= null) top.get(); } catch (Exception e) { System.out.println("Error Futures");} } Trådene som startes er vanlige (indre) klasser med en parallell metode run() : class FindExec implements Runnable { int index; public FindExec(int ind) { index = ind; } public void run() { <kall parallell metode> }}

Mange muligheter med slike pooler: Man kan lukke poolen: pool.shutdown(); Man kan lage ca. ulike typer av pooler: Fast størrelse, variabel størrelse, cachete (gjenbruk), med tidsforsinkelse, med og uten ThreadFactory (et objekt som lager tråder når det trengs),.. Det hele koker ned til spørsmålene: Vi trenger å ha en rekke tråder som parallelliserer problemet vårt Er en slik trådpool effektiv?

&)Test på effektivitet tre implementasjoner av parallell FindMax i : int [] a ; speedup (større tall er bedre): a) Med ExecutorService og FixedThreadPool a)med like mange tråder som kjerner: a) Med x tråder som kjerner b) Med modell kode med CyclicBarrier for start&vent n a)pool x a) Pool x b) Barrier..7,9.9,,.,,.9,99,.,,9.,,97 Konklusjon: Om lag like raske for større n

III) Nok et problem/overraskelse med JIT-kompilering Som vi husker går JIT-kompilering i flere steg: Oversettelse til maskinkode av hyppig brukt kode Mer bruk optimalisering av den maskinoversatte koden Si bruk > ganger Enda mer bruk super-optimalisering av koden en gang til Først noen resultater; sammenligning av Barrier-løsningen av FinnMax med samme løsning skrevet litt annerledes: Speedup: n b) Barrier Ny Barrier,9,,,,,7,,,9 7,9,97 9,8

Konklusjon: Hurra, en mye bedre parallellisering? Speedup:,97 < 9,8!!! En klart bedre løsning? At speedup er mye større, er det da sikkert at parallelliseringen er mye bedre/raskere? Svar: JA, men bare hvis den sekvensielle koden som parallelliseringen sammenlignes med er den samme. Det eneste som var forskjellig mellom disse to programmene var at jeg hadde forsøkt å gjøre den sekvensielle koden raskere ved å inline - selve koden på kallstedet. Den parallelle koden var den samme. Vi tester og ser etter hva som har skjedd her!

Hva var forskjellen mellom de to Barrier-kodene for n = Fra b) Barrier programmet (>java FinnBarrier.java): Median parallel time :.977 Median sequential time:.88,, Speedup:.98, n = Fra Ny Barrier-programmet (INFPara\FinnMax>java FinnM ): Max verdi parallell i a:99989, paa:.997 millisek. Max verdi sekvensiell i a:99989, paa:.9 millisek. Median sequential time:.99, median parallel time:.8, n=, Speedup: 9.8 Konklusjon: Det er særlig den sekvensielle kjøretiden er langsommere, ikke at den parallelle er raskere.

Hva var forskjellen mellom de to kodene UTEN JITkompilering, n = (java Xint BarrierMax..)? Fra b) Barrier programmet: Median parallel time:.779 Median sequential time:77.8, Speedup:., n = Fra Ny Barrier-programmet: Max verdi parallell i a:99989, paa:.8 millisek. Max verdi sekvensiell i a:99989, paa:.8 millisek. Median sequential time:.878, median parallel time:.89, n=, Speedup:.9 Konklusjon: Det er særlig den sekvensielle kjøretiden som er bedre optimalisert, ca.x for b) mens bare ca. x for NyBarrier! Hvorfor? 7

Her er forskjellen mellom de to programmene a) Ny Barrier, langsom (x) sekvensiell optimalisering. Koden for sekvensiell metode er lagt rett inn i en større metode (utfor() ) som ikke kalles mange ganger b) Barrier, mye raskere sekvensiell x optimalisering.laget en metode av sekvensiell kode som kalles fra utformetoden. // inlined av meg:sekvensiell finnmax t = System.nanoTime(); totalmax = ; for (int i=;i < a.length;i++) if (a[i] > totalmax) totalmax = a[i]; t = (System.nanoTime()-t); seqtime[j] =t/.; int dosequentialversion(int [] a) { int max= -; for (int i = ; i< a.length; i++) if (a[i] > max) max = a[i]; return max; } // end dosequentialversion Optimalisatoren i JIT ser ut til å være langt bedre til å optimalisere (små) metoder enn en løkke inne i en større metode. 8

Observasjon JIT-kompilering/optimalisering Vi bør ta hensyn til hvordan optimalisatoren virker Generelt ser den ut til å greie å øke hastigheten på interpretert kode med x Små metoder som vi finner i klassen for en bit array for pimtall implementer i en byte-array (med metoder som isprime(i), setnotprime(), nextprime(m), ) og : int dosequentialversion(int [] a) i FinnMax er meget velegnet for optimalisering Så små metoder kan optimaliseres i vårt tilfelle: 77/= x Når vi skriver kode bør vi bruke denne kunnskapen fordi Gir enklere kode lettere å skrive Gir raskere kode Grunnen til dette er vel at ved at når vi har lagt kode inn i en metode, sier vi at avhengigheten til resten av programmet er begrenset, grovt sett til parameterne. Lettere da å optimalisere! Oppskrift: Best optimalisering hvis en metode bare behandler parameterne og lokale variable i metoden. 9

IV) Problemer med forholdet mellom long og int Java prøver hele tiden å være mest rask/økonomisk når den regner ut uttrykk: Regner ut billigst først og så konverterer ved tilordning. public static void main (String [] args) { int m = ; long tall = m*m; System.out.println("M:"+m+", tall (m*m):"+ tall); tall = (long)m*m; System.out.println("M:"+m+", tall((long)m*m):"+ tall); tall = (long)(m*m); System.out.println("M:"+m+", tall((long)(m*m):"+ tall); tall = (long)m*(long)m; System.out.println("M:"+m+", tall((long)m*(long)m):"+ tall); } M:, tall (m*m): -7 M:, tall((long)m*m): M:, tall((long)(m*m): -7 M:, tall((long)m*(long)m):

Hva har vi sett på i uke 9:. En første gjennomgang av parallellisering av Oblig Den sekvensielle og a) og b) parallellisert m. tips. En effektiv Threadpool? Executors.newFixedThreadPool. Mer om effektivitet og JIT-kompilering!. Om et problem mellom long og int