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

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

INF2440 Uke 11, v2016 om Goldbachs problem og Oblig 2,3. 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 12, v2014. Arne Maus OMS, Inst. for informatikk

Uke 13 inf2440 v2016. Arne Maus PSE-gruppa Ifi, Uio

7) Radix-sortering sekvensielt kode og effekten av cache

UNIVERSITETET I OSLO

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

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

UNIVERSITETET I OSLO

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 10, v2014 : Arne Maus OMS, Inst. for informatikk

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

INF2440 Uke 6, våren2014 Mer om oppdeling av et problem for parallellisering, mye om primtall + thread-safe. 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

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

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

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

UNIVERSITETET I OSLO

INF2220 høsten 2017, 12. okt.

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

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

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

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

Uke 12 inf2440 v2018. Eric Jul PSE-gruppa Ifi, UiO

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

UNIVERSITETET I OSLO

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

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

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

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

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

UNIVERSITETET I OSLO

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

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

UNIVERSITETET I OSLO

2 Om statiske variable/konstanter og statiske metoder.

Rekursjon. Binærsøk. Hanois tårn.

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

Løsningsforslag 2017 eksamen

Arne Maus OMS, Inst. for informatikk

Java PRP brukermanual

INF2220 høsten 2017, 19. okt.

Parallellprogrammering og Sortering INF nov. 2015

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

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

INF NOV PARALLELL SORTERING. Arne Maus, PSE, Ifi

EKSAMEN. Dato: 18. mai 2017 Eksamenstid: 09:00 13:00

INF2220: Time 12 - Sortering

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 5, våren2016. Arne Maus PSE, Inst. for informatikk

INF 1000 høsten 2011 Uke september

INF1000 undervisningen INF 1000 høsten 2011 Uke september

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

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

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

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

INF1010 notat: Binærsøking og quicksort

Rekker (eng: series, summations)

Forelesning inf Java 4

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

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

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

Repetisjon: operatorene ++ og -- Java 5. Nøtt. Oppgave 1 (fra forrige gang) 0 udefinert udefinert. Alternativ 1 Prefiks-operator

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

Binære søketrær. Et notat for INF1010 Stein Michael Storleer 16. mai 2013

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

alternativer til sortering og søking binære trær søketrær Ikke-rekursiv algoritme som løser Hanois tårn med n plater

UNIVERSITETET I OSLO

INF110 Algoritmer og datastrukturer TRÆR. Vi skal i denne forelesningen se litt på ulike typer trær:

INF2220 høsten 2016, 9. nov.

Norsk informatikkolympiade runde

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister

Del 4 Noen spesielle C-elementer

INF2220 høsten 2015, 5. nov.

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

INF1000 : Forelesning 4

Dagens temaer. Sortering: 4 metoder Søking: binærsøk Rekursjon: Hanois tårn

UNIVERSITETET I OSLO

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

Oppgave 1. Oppgave 2. Oppgave 3. Prøveeksamen i INF1000. Ole Christian og Arne. 23. november 2004

Prøveeksamen i INF1000. Ole Christian og Arne. 23. november 2004

UNIVERSITETET I OSLO

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

2 Om statiske variable/konstanter og statiske metoder.

UNIVERSITETET I OSLO

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

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

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

Øvingsforelesning 3 Python (TDT4110)

UNIVERSITETET I OSLO

Oppgave 1. INF1000 Uke 13. Oppgave 2. Oppgave 3. Er dette lovlige deklarasjoner (når de foretas inni en metode)? JA NEI

Rekker (eng: series, summations)

EKSAMEN med løsningsforslag

INF1010 Rekursjon. Marit Nybakken 1. mars 2004

Transkript:

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

Fra hjemmesida til INF2440: Plan for resten av semesteret: Forelesninger: 8. april (i dag), 15.april, 22.april, 29.april og 6 mai (oppsummering) Oblig 4: Fullføring av parallell Radix-sortering (2 siffer) - frist 30. april. Tekst lagt ut. Prøveeksamen: 20. mai med gjennomgang og tips (mer info senere) Eksamen: 2. juni 2

Hva så vi på i Uke10 Hvor lang tid tar de ulike mekanismene (les/skriv, new, metodekall, arrayer,..) i Java 6 og 8. Automatisk parallellisering av rekursjon PRP- Parallel Recursive Procedures Nåværende løsning (Java, multicore CPU, felles hukommelse) implementasjon: Peter L. Eidsvik Demo av to eksempler med kjøring Ikke gå i fella: Et Rekursivt kall = En Tråd Halvautomatisk oversettelse (hint/kommandoer fra kommentarer) Hvordan virker en kompilator (preprosessor) for automatisk parallellisering Prinsipper ( bredde-først og dybde-først traversering av r-treet) Datastruktur Eksekvering Krav til et program som skal bruke PRP 3

Hva skal vi se på i Uke 11 I) Hvorfor lage en egen IntList istedenfor ArrayList <Integer> II) Optimalisering av Oblig 2 og 3 noen resultater II) Debugging av parallelle programmer ett eksempel III) Et større problem uløst problem siden 1742 Vil du tjene $1 mill.? Løs Goldbach s påstand (alternativt: motbevis den) Formulering og skisse av løsning av tre av Goldbachs problemer Parallellisering av disse (ukeoppgave neste uke) IV) Om Oblig 3 og 4 4

class IntList{ int [] data; int len =0; IntList( int len) { data = new int [Math.max(1,len)]; } IntList() { data = new int [32]; } void add( int elem) { if (len == data.length-1) { int [] b = new int [data.length*2]; for (int i = 0; i < data.length; i++) b[i] = data[i]; data =b; } data[len++] = elem; } // end add void clear(){ len =0; } // end clear int get ( int pos){ // error antar at svaret brukes til array-indeks if (pos > len-1 ) return -1; else return data [pos]; } //end get int size() { return len; } //end size } // end class IntList 5

Fra testprogrammet long ILSek (int n) { IntList itlist = new IntList(n); long j = 1; for (int i =0; i<n; i++) itlist.add(i); for (int i =0; i<n; i++) j +=itlist.get(i); return j; }// end ILSek long ALSek (int n) { ArrayList <Integer> alist = new ArrayList<Integer>(n); long j = 1; for (int i =0; i<n; i++) alist.add(i); for (int i =0; i<n; i++) j +=alist.get(i); return j; }// ens ALSek.. long t = System.nanoTime(); // start tidtaking IntList sum += ILSek(n); t = (System.nanoTime()-t);.. t = System.nanoTime(); // start tidtaking ArrayList sum += ALSek(n); t = (System.nanoTime()-t); 6

Forskjeller på Integer og int - størrelse Integer er et objekt som brukes å holde et heltall. Hvert heltall tar da 12 byte (object header) + 4 byte (int) int er en basaltype som tar 4 byte En int [] array har ett array objekt for hver rad dvs. ekstra 12 byte per rad + ett array-objekt for hver dimensjon (2,3,..) se: http://stackoverflow.com/questions og http://www.javamex.com/tutorials/memory/object_memory_usage.shtml a normal object requires 8 bytes of "housekeeping" space; arrays require 12 bytes (the same as a normal object, plus 4 bytes for the array length). If the number of bytes required by an object for its header and fields is not a multiple 8, then you round up to the next multiple of 8. +-----------+---------------+----------------- +----------+ mark word klass pointer array size (opt) padding +-----------+---------------+------------------+----------+ Har vi 1000 Integer i en array er det: 1000x 16 (Integer objekter) + 16 (array overhead) + 8x1000 (pekere) = 24 016 byte Har vi int [] a = new int[1000} er det 8+16 + 4*1000 = 4 024 byte 7

Tidsforbruk int og Integer Integer Når vi skal lagre et heltall i en Integer, må den først pakkesinn (boxing) i et objekt vi lager + en peker til den i arrayen av Integer-pekere Når vi skal lese en heltallsverdi fra en Integer, må vi først følge en peker for å lokalisere Integer-objektet, og så lese ut int-verdien (unboxing) int-array Lesing og skriving i en int [] er mye raskere tilsvarende som å finne og skrive en peker i Integer-arrayen. 8

Test på lage (add) n stk Integer i ArrayList og i IntList og lese dem (get) Test av IntList mot ArrayList for aa oppbevare heltall med 4 kjerner, og 4 traader, Median av:3 iterasjoner (lager array 128 lang først og så kopierer) n IntList.tid(ms) ArrayList.tid(ms) Speedup 100 000 000 2024.9678 65388.7015 32.29 10 0000 00 93.0643 316.7953 3.40 1 000 000 6.5577 12.7090 1.94 100 000 0.6709 0.9978 1.49 10 000 0.0928 0.1483 1.60 1 000 0.0087 0.0141 1.61 100 0.0011 0.0015 1.33 10 0.0004 0.0004 1.00 (tallene kan variere mye men IntList er alltid en god del raskere enn ArrayList <Integer>- eks. lager stor nok array initierer med n: 100 000 000 1070.6890 55599.8010 51.93) Hvorfor ikke en større speedup? 9

Ser på performance i Task manger Før kjøring 10

Kjøring av IntList test ser på performance i Task manger Kjøring av IntList test 15% 100/8 11

Ser ut til at optimaliseringen parallelliserer ArrayList operasjonene ser på performance i Task manger Kjøring av ArrayList test 73 % må komme av parallellisering Derfor er ikke ArrayList så mye langsommere enn IntList 12

I) Om speedup av Oblig2; optimal sekvensiell og parallell kode: n sekv(ms) para(ms) Speedup PerElemSek PerElemPar EratosthesSil 2000000000 14131.98 7060.41 2.00 Faktorisering 2000000000 24586.18 15845.43 1.55 245.8618 158.4543 Total tid 2000000000 38613.92 22938.85 1.68 EratosthesSil 200000000 1078.20 268.08 4.02 Faktorisering 200000000 5970.54 2817.03 2.12 59.7054 28.1703 Total tid 200000000 7050.84 3085.10 2.29 EratosthesSil 20000000 68.80 17.71 3.88 Faktorisering 20000000 683.02 407.84 1.67 6.8302 4.0784 Total tid 20000000 747.09 425.56 1.76 EratosthesSil 2000000 6.02 1.92 3.14 Faktorisering 2000000 146.56 214.39 0.68 1.4656 2.1439 Total tid 2000000 152.12 216.29 0.70 EratosthesSil 200000 1.02 0.61 1.65 Faktorisering 200000 67.47 163.95 0.41 0.6747 1.6395 Total tid 200000 68.53 164.62 0.42 EratosthesSil 20000 0.06 0.10 0.55 Faktorisering 20000 14.06 23.98 0.59 0.1406 0.2398 Total tid 20000 14.12 24.20 0.58 EratosthesSil 2000 0.01 0.27 0.05 Faktorisering 2000 23.20 46.89 0.49 0.2320 0.4689 Total tid 2000 23.24 47.25 0.49 13

Ikke-optimal, men riktig kode // Sekvensiell faktorisering av primtall ArrayList<Long> factorize (long num) { ArrayList <Long> fakt = new ArrayList <Long>(); int pcand =2; long pcand2=4l, rest= num; while (rest > 1 && pcand2 <= num) { while ( rest % pcand == 0){ fakt.add((long) pcand); rest /= pcand; } pcand = nextprime(pcand); pcand2 =(long) pcand*pcand; } if (rest >1) fakt.add(rest); return fakt; } // end factorize Tips: Hva er grensene når vi har funnet første faktor 14

Manglende optimalisering av sekvensiell faktorisering n sekv(ms) para(ms) Speedup EratosthesSil 2000000000 14209.31 7205.05 1.97 Faktorisering 2000000000 441606.92 16189.86 27.28 Total tid 2000000000 455816.24 23394.92 19.48 EratosthesSil 200000000 1107.95 245.96 4.50 Faktorisering 200000000 45323.05 2864.98 15.82 Total tid 200000000 46431.01 3110.93 14.93 EratosthesSil 20000000 66.82 19.10 3.50 Faktorisering 20000000 5745.96 365.60 15.72 Total tid 20000000 5812.79 384.70 15.11 EratosthesSil 2000000 6.13 2.13 2.87 Faktorisering 2000000 546.41 228.45 2.39 Total tid 2000000 552.55 230.58 2.40 Her har vi ikke-optimal sekvensiell kode, men optimal parallell kode 15

3999999999999999899 = 107*37383177570093457 3999999999999999900 = 2*2*3*5*5*89*1447*1553*66666667 3999999999999999901 = 19*2897*72670457642207 3999999999999999902 = 2*49965473*40027640687 3999999999999999903 = 3*101*241*54777261958561 3999999999999999904 = 2*2*2*2*2*1061*117813383600377 3999999999999999905 = 5*7*13*8791208791208791 3999999999999999906 = 2*3*3*17*31*421674045962471 3999999999999999907 = 14521697*275449900931 3999999999999999908 = 2*2*11*168409*539811357523 3999999999999999909 = 3*2713*491460867428431 3999999999999999910 = 2*5*399999999999999991 3999999999999999911 = 167*659*3581*86629*117163 3999999999999999912 = 2*2*2*3*7*7*4127*669869*1230349 3999999999999999913 = 239*16736401673640167 39999999999999899 = 39999999999999899 39999999999999900 = 2*2*3*5*5*7*952381*19999999 39999999999999901 = 181*229*229*47237*89213 39999999999999902 = 2*16103*1242004595417 39999999999999903 = 3*191*69808027923211 39999999999999904 = 2*2*2*2*2*47*7867*19843*170371 39999999999999905 = 5*151*230341*230007391 39999999999999906 = 2*3*3*3*3*3*3*2089*13133002513 39999999999999907 = 7*7*7*29*4021312958681 39999999999999908 = 2*2*11*19*7621*6278295493 Noen faktoriseringer Observasjoner : - Hvor mange faktorer er det i de fleste? - Hvor store er tallene? - Deler vi talllinja av primtall (2 milliarder) på 8 kjerner får vi 250 mill. til hver tråd - Hvilken tråd finner de fleste faktorene? 16

Optimalisering av parallell faktorisering: Ved parallellisering av faktorisering, får hver kjerne (8) sin del av primtallene (i eksempelet primtallene på 25 bit i bittabellen hver) Hvor stor sannsynlighet er det for at et vilkårlig tall k er delbart på 3 - uten rest? Hvor stor sannsynlighet er det for at et vilkårlig tall k er delbart på 4093 - uten rest? Mens vi i det sekvensielle tilfellet hadde kontroll over resten av tallet har vi det ikke på samme måte parallell faktorisering. Vi må først finne det gode optimaliseringa sekvensielt, og gjøre noe av det samme med en felles variabel (AtomicLong) mellom trådene. 17

Hvorfor får vi ulik speedup, og bare for store verdier av n? n sekv(ms) para(ms) Speedup EratosthesSil 20000000 68.80 17.71 3.88 Faktorisering 20000000 683.02 407.84 1.67 Total tid 20000000 747.09 425.56 1.76 EratosthesSil 2000000 6.02 1.92 3.14 Faktorisering 2000000 146.56 214.39 0.68 Total tid 2000000 152.12 216.29 0.70 EratosthesSil 200000 1.02 0.61 1.65 Faktorisering 200000 67.47 163.95 0.41 Total tid 200000 68.53 164.62 0.42 EratosthesSil 20000 0.06 0.10 0.55 Faktorisering 20000 14.06 23.98 0.59 Total tid 20000 14.12 24.20 0.58 Ulik speedup på de to algoritmene: Overhead: startup synkronisering Lastballansering mellom trådene? Effekter av cachen (se begge algoritmer)? 18

Tips til utskrift mm Saml inn tidene først i en fler-dimensjonal double[][][] array, og skriv det så ut oversiktlig (funksjon, n, iterasjon) Faktoriseringa kan skrives ut mens du finner den. (kan ikke lage array av ArrayList-er.) Lag utskriftsmetoder som skriver ut både på fil og skjerm /** for også utskrift på fil */ synchronized void println(string s) { ut.outln(s); System.out.println(s); } /** for også utskrift på fil */ synchronized void print(string s) { ut.out(s); System.out.print(s); } 19

II) Debugging feilfjerning parallelt Antar at vi har et program som lar seg starte opp Felles problem i sekvensiell og parallell kode? Råd0 : Hvis ikke sekvensiell kode virker, fix den Er det en feil her? Terminerer programmet Gale resultater Samme feil hver gang? Et sekvensielt program kan gjøres deterministisk (eks. Random r = new Random(123) vil produsere samme tall-rekke ved neste kjøring) Parallelle programmer kan ikke gjøres deterministiske Never same result twice Er feil avhengig av størrelsen på problemet som løses av programmet, av n? Råd1: Finn først det minste eksempelet som feiler 20

Du har en feil som kan reproduseres på et relativt lite eksempel EKS fra debugging av min parallelle Oblig2-løsning (parallell ErSil + parallell faktorisering.): para: 39910 = 65*2*307 NEI!! (65 = 13*5) Symptomer: Kom ikke hver gang (bare ca. hver 4. gang)) Kom ikke i den sekvensielle faktoriseringa. Spørsmål:: Er det en tidsavhengig feil? Svar1? Sannsynligvis det Eller det bare en sekvensiell feil i den parallelle koden? Svar2: Mindre sannsynlig. Nesten alle parallelle faktoriseringer er riktige (og ingen andre brukte 65 som primtall) 21

para: 39910 = 65*2*307 - ikke Er det feil i Eratosthenes bit-tabell eller i selve faktoriseringa Jeg prøvde ut flere optimaliseringer. Sjekket først synkronisering Viktig: At bare en tråd (tråd-0) initierer konstanter o.l., og genererer alle primtall < 200 =14,, og at alle andre tråder venter på at det er ferdig. Råd2: Ikke debug ved å gå linje for linje gjennom koden! Råd3: Bruk binær feilsøking: Plasser en System.out.println(..) midt i koden og sjekk de data som der skrives ut virker de riktige? Hvis ja: feilen nedenfor, nei: feilen er ovenfor Her: Siden problemet feilet med n=200, så: Skrev ut alle primtallene < n (200) Vi hadde to algoritmer (Eratosthenes eller faktoriseringen) var det den første eller den andre? Debug:2 Debug:3 Debug:5 Debug:7 Debug:11 Debug:13 Debug:17 Debug:23 Debug:29 Debug:33 Debug:39 Debug:41 Debug:47 Debug:51 Debug:53 Debug:57 Debug:59 Debug:69 22

Noen av Primtallene var altså gale (for mange) Første feil : 33! Feilen var altså i Erotasthenes Sil i parallell: Algoritmen, skisse (for n=200, =14): Finn først alle primtall < sekvensielt Dette er de vi trenger for å lage alle under 200 Del tallinja 1..200 i antallkjerner (8) biter, jeg fikk: left:1, right:27 left:1, right:13 left:71, right:83 left:99, right:200 left:85, right:97 left:57, right:69 left:43, right:55 left:15, right:27 left:29, right:41 Ikke opplagt riktig Debug:2 Debug:3 Debug:5 Debug:7 Debug:11 Debug:13 Debug:17 Debug:23 Debug:29 Debug:33 Debug:39 Debug:41 Debug:47 Debug:51 Debug:53 Debug:57 Debug:59 Debug:69 23

Råd4: Litt analyse (papir og blyant): Denne metoden ble brukt av både sekvensiell innledende fase av parallell alle < (rød) og parallell (sort): Den er også tilpasset grensene for hva innholdet av en byte er: byte[0] 1-13, byte[1] 15-27, Siden 200 =14 > 13, så OK? De andre grensene så ut til å være veldig skjevt fordelt? Men siden da jeg regnet ut antall primtall per kjerne: (200 /8) /14)*14 = (25/14)*14 = 14 og siste tråd tar resten, er dette OK. Konklusjon: Tråd-2 (29-41) feiler med 3-er avkryssingene left:1, right:27 left:1, right:13 left:71, right:83 left:99, right:200 left:85, right:97 left:57, right:69 left:43, right:55 left:15, right:27 left:29, right:41 24

Hvis den alltid tror at 65 er et primtall, hvorfor går dette ofte OK? Råd5: Forstå feilen Som oftest får vi følgende svar : 39910 = 2*5*13*307 som er helt riktig! Og hvorfor vil den sekvensielt alltid ha det riktig selv om den tror at 65 er et primtall? Se på koden: 25

Hvis 65 = 5*13 er to faktorer i et tall num og vi allerede har delt ned num med de mindre primtallene 5 og 13, så finner vi ikke 65 en faktor (den er dividert bort) Dividerer vi først ned med 5 og 13 (alltid ved sekvensiell), så vil vi aldri oppdage 65. Hvis tråd2 deler num ned før tråd0, vil vi oppdage 65 ellers ikke. // Sekvensiell faktorisering av primtall ArrayList<Long> factorize (long num) { ArrayList <Long> fakt = new ArrayList <Long>(); int pcand =2; long pcand2=4l, rest= num; while (rest > 1 && pcand2 <= num) { while ( rest% pcand == 0){ fakt.add((long) pcand); rest /= pcand; } pcand = nextprime(pcand); pcand2 =(long) pcand*pcand; } if (rest >1) fakt.add(rest); return fakt; } // end factorize 26

Feilen - konklusjon: Diagnose enten ble 3-ere, 5ere..avkrysset galt i byte[1], byte[2],.., eller så har vi et timing-problem FASIT: Hvor starter vi neste kryss fra primtall p i en byte (bit-nummeret) som har sitt venstre, minste bit i left. p 2 ikke er i inneværende byte. Hva er verdien til start 2p 2p 2p 2p 2p start p 2 left I denne byten skal vår tråd krysse av start = ((left - )/( )) ( ) + ; while(start < left) start += ; 27

Avsluttende bemerkninger om debuging av parallelle programmer: Råd6: Legg System.out.println(s) innn i en: synchronized void println(string s) i den ytre klassen Da vil utskrifter ikke blandes. Råd7: Hvis ingen ting skjer når vi starter programmet: Lag en 5-6 setninger av typen : print(«a»); print(«b»);..og plasser de jevnt over rundt i programmet (i toppen av løkker) Da ser vi hvor langt programmet kom før det hang seg. Start å lete etter siste bokstav i koden som kom ut. 28

III) Christian Goldbachs påstand i 1742: Alle partall m =n+n > 4 kan skrives som en sum av to primtall som er oddetall. m = p1+p2 ( p1 p2) Eks: 6 = 3+3, 14 = 7+7 og 14 = 11+3,. Antall slike ulike summer av to primtall for en gitt m kaller vi G(m). Bevis at G(m) > 0 m. 29

vel egentlig..: Goldbach foreslo at alle tall kan skrives som sum av tre primtall. Den store matematiker Euler ryddet opp i det og utledet lett: Alle oddetall kan skrives som sum av tre primtall Alle partall kan skrives som summen av to primtall Goldbach mente selv at 1 var et primtall (naturlig nok) Goldbachs påstand er ikke bevist matematisk for partall. Praktisk på datamaskiner (Wikipedia): T. Oliveira e Silva is running a distributed computer search that has verified the conjecture for n 4 10 18 (and doublechecked up to 4 10 17 ). One record from this search: 3325581707333960528 needs minimal prime 9781 (=p1 : n =p1+p2)) Dvs for de fleste tall som kan representeres i en long 30

Goldbachs brev til Euler hvor han foreslår at alle tall kan skrives som sum av tre primtall 31

G(m) for alle tall < 1000 varierer mye, men har en litt uklar nedre grense som vi ikke greier å vise er >0 32

G(n) for alle tall < 1 mill varierer mye, men har en skarp nedre grense som vi ikke greier å vise er > 0! 33

Hvordan vise Goldbach med et program En riking i USA har utlovet $1mill for løsning på 10 matematiske problemer som lenge var uløst. Goldbach er en av disse problemene, og premien er ikke hentet. To måter å vise Goldbach: Komme med et matematisk bevis for at den er sann. Komme med et mot-eksempel: Partallet M som ikke lar seg skrive som summen av to primtall. Å bevise noe om sum (+) er mye vanskeligere enn faktorisering (*) bla. fordi ethvert N tall har en entydig faktorisering mens N har mange summer (faktisk N summer med to addender, og svært mange flere med mer enn 2 addender) 34

Hvordan løser vi dette? Første sekvensielt Hvilket program skal vi lage? a) Prog1: Som for alle tall m=6,8,.,n finner minst én slik sum m= p1+p2 b) Prog2: Som regner ut G(m) for m=6,8,.,n c) Prog3: Som tester noen tall > 4 10 18 om Goldbach gjelder også for disse tallene (sette ny rekord ikke testet tidligere, kanskje finne ett tall som ikke lar seg skrive som summen av to primtall.) Forskjellen på Prog1 og Prog3 er at i Prog1 antar vi at vi vet alle primtall < m, det trenger vi ikke i Prog3 (som da blir en god del langsommere). Prog1 og Prog2 bruker bare Eratosthenes Sil fra Oblig2. Prog3 bruker både Eratosthenes Sil og faktoriseringa fra Oblig2. 35

Skisse av Prog1 : Finn minst én slik sum m=p1+p2, m <n, m partall, p1 p2; sekvensielt program <Les inn: n> <Lag e= Eratosthens Sil(n)> for (int m = 6 ; m < n; m+=2) { // for neste tall m, prøv alle primtall p1 m/2 for (int p1 = 3, p1 <= m/2; e.nextprime(p1){ if ( e.isprime(m-p1)) { // System.out.println( m+" = "+ p1 + " + "+ (m-p1) ); break; } } // end p1 if (p1 > m/2) System.out.println( " REGNEFEIL: (Goldbach bevist for n < 4*10**18:" + m + " kan ikke skrives som summen av to primtall "); } // end m 36

Skisse av Prog2 : Finn G(m) antall slike summmer: m = p1+p2, m <n, m partall, p1 p2; sekvensielt program <Les inn: n> <Lag e= Eratosthens Sil(n)> int Gm; for (int m = 6 ; m < n; m+=2) { Gm = 0; // for neste tall m, prøv alle primtall p1 m/2 for (int p1 = 3, p1 <= m/2; e.nextprime(p1){ if ( e.isprime(m-p1)) { Gm++; } } // end p1 if (Gm == 0) println(" REGNEFEIL: (Goldbach bevist for n < 4*10**18):" + m + " kan ikke skrives som summen av to primtall "); else println(" Antall Goldbachsummer i "+m+" er:"+gm); } // end m 37

Betraktninger før skissen til Prog3 Det største antall bit vi kan ha i en bit-array = maksimalstørrelsen av en int ( litt for overflyt) max int = 2 147 483 647 Prøver å lage en Erotosthanes Sil med n= 214748000 Da kan vi faktoriser tall < 4 611 670 350 400 000 002 Dette gir oss plass for å prøve ut 611 670 350 400 000 000 tall > 4*10 18 Egentlig skal vi jo prøve ut alle p1 < m/2, men forskningen viser: (One record from this search: 3 325 581 707 333 960 528 needs minimal prime 9781 (= den største p1 : n =p1+p2)) Dvs, satser på at: Er det en Goldbach sum for 19-sifrete tall, så er p1 < 15 000 (som er en del større enn 9 781) 38

Original skisse av Prog3 : Finn minst én slik sum m=p1+p2, sekvensielt program m, 4*10 18 < m < 4*10 18 + antall, m partall, p1 p2; <Les inn: antall> <Lag e= Eratosthens Sil(2147480000)> // nær øvre grense for int for (long m = 4*10 18 ; m < 4*10 18 +antall; m+=2) { // for neste tall m, prøv alle primtall p1 m/2 for (int p1 = 3, p1 <= m/2; e.nextprime(p1){ if ( e.faktorisering (m-p1).size() == 1 )) { // Funnet Goldbach sum break; } } // end p1 if (p1 > m/2) System.out.println( " BINGO: Funnet $1. mill:" + m + " kan ikke skrives som summen av to primtall "); } // end m Hvorfor er denne en riktig, men dårlig algoritme?? 39

Skissen av Prog3 : Er svært lite effektiv fordi en av operasjonene er tar mye lenger tid enn alle andre og gjentas veldig mange ganger med samme argument <Les inn: antall> <Lag e= Eratosthens Sil (2147480000)> // nær øvre grense for int for (long m = 4*10 18 ; m < 4*10 18 +antall; m+=2) { // for neste tall m, prøv alle primtall p1 m/2 for (int p1 = 3, p1 <= m/2; e.nextprime(p1){ if ( e.faktorisering (m-p1).size() == 1 )) { println(«ok:»+ m + «= «+(m-p1) + «+» +p1); } } // end p1 if (p1 > m/2)system.out.println(" BINGO: "+ m +", ikke sum av to primtall"); } // end m e.faktorisering (m-p1).size() tar hver ca 1/6 sek i parallell, men vi må teste ca 40 tall før vi finner et primtall (og da tar det 1. sek), og bare hvert 10 primtall passer (men i verste tilfellet er det hvert 1000 primtall). Dvs. Å finne en GSum på denne måten tar ca. 100 sek. hver gang vi får OK, eller ca. 115 døgn på å lage 100 000 slike nye summer. Det må finnes en bedre algoritme som bla. ikke beregner de samme store primtallene svært mange ganger. 40

Ide: Hvis det er en sum m = p1+p2, så er p1 < 15 000 Lag en int [] p1funnet, si 100 000 lang, og en ArrayList storeprimtall med de første 10 000 store primtall > 4*10 18-15 000. storeprimtall 4*10 18 4*10 18-15 000 småprimtall fra e.. 13 11 7 5 3.. 13 11 7 5 3 p1funnet småprimtall fra e Legg sammen alle små primtall p1 fra e (3,5,..) med først den minste fra storeprimtall, og lagr p1 i p1funnet for alle slike summer som er > 4*10 18 Gå neste store primtall p2 og gjenta summeringene med de samme små primtallene p1 fra e. osv Når alle slike summer er utført, håper vi at det i p1funnet står en p1 i hver plass som representerer tallene 4*10 18, 4*10 18 +2, 4*10 18 +4,, 4*10 18 +100 000 Står det ikke en p1 i en av disse plassene, er det kanskje et tall som ikke har en GoldbachSum ($1mill.?) Hvorfor begynne adderingen på 4*10 18-15 000, hvorfor ikke på 4*10 18? 41

Skisse1 av ny algoritme for prog3 <Les inn: antall> a) Lag e= Eratosthens Sil(2147480000)> // nær øvre grense for int b) Lag en int[] p1funnet som er ca. 200 000 lang> c) Lag alle store primtall vi trenger og lagre dem i en ArrayList storeprimtall> d) for hvert element p2 i storeprimtall, adder de små primtallene p1 fra e slik at summen er < 4*10 18 + 200 000 og lagre disse p1-ene i p1funnet> e) gå så gjennom p1funet og skriv ut de 100 000 summene du forhåpentligvis kan finne der> hvis p1funnet[i]!= 0 så representerer det summen: m = p1 + p2 i+ 4*10 18 = p1funnet[i] + (i+ 4*10 18 - p1funnet[i] ) < legg til evt optimalisering av pkt. d) > 42

Programskisse av ny Prog3 : Den gamle skissen var svært lite effektiv fordi å finne store primtall tar mye lenger tid enn alle andre og gjentas veldig mange ganger med samme argument <Les inn: antall> <Lag e= Eratosthens Sil(2147480000)> // nær øvre grense for int long start = 4*10 18 15 000, m; ArrayList storeprimtall = new ArrayList(); // plass til 10 000 store primtall > start int [] p1found = new int [100 000] ; // p1 i summen: m = p1+p2 // lag først alle store primtall for ( m = start ; m < 4*10 18 +antall; m+=2) { if (e.faktorisering(m).size==1) storeprimtall[(m-start)/2] = m; } int i =0; for (m = storeprimtall.get(i); i < storeprimtall.size(); i++) { // for neste tall m, legg til alle primtall p1 for (int p1 = 3, p1 <= 200 000 ; e.nextprime(p1) p1found[(m-start+p1)/2] = p1; } m = 4*10 18 ; i =0; while ( p1found[i]!= 0 && i++ < 100 0000 ) println(m + i *2) + «=«p1found[i] «+» + (m+i*2 - p1funnet[i] ) ); 43

Prog1: Hvordan parallellisere å finne én sum? Vi har en dobbelt løkke (m og p1) Parallelliser den innerste løkka: Deler opp primtallene og lar ulike tråder summere med ulike p1 Sannsynligvis uklokt? Parallelliserer den ytterste løkka: Hvis vi lar hver tråd få 1/k-del av tallene å finne p1 for. Med n= 2mrd. får hver tråd 250 mill. tall å sjekke. <Les inn: n> <Lag e= Eratosthens Sil(n)> for (int m = 6 ; m < n; m+=2) { // for neste tall m, prøv alle primtall p1 m/2 for (int p1 = 3, p1 <= m/2; e.nextprime(p1){ if ( e.isprime(m-p1)) { break; // funnet sum } } // end p1 if (p1 > m/2) System.out.println(" REGNEFEIL for "+ m); } // end m Litt ulik belastning på trådene, da større tall må lete lenger etter den første p1 hvor m-p1 er primtall. Parallelliserer ved å lage en rekursjon på ytterste løkke. Kan bruke PRP Mye kortere kode Konklusjon: Forsøker først å parallellisere den ytterste løkka? 44

Viktig poeng: Hvilke rutiner bruker vi? Vi har sekvensielle og parallelle versjoner av Eratosthenes Sil og Faktorisering. Hvilken versjon bruker vi i Prog1,2,3? <Les inn: antall> /* Prog3 skisse */ <Lag e= Eratosthens Sil(2147480000)> // nær øvre grense for int for (long m = 4*10 18 ; m < 4*10 18 +antall; m+=2) { // for neste tall m, prøv alle primtall p1 m/2 for (int p1 = 3, p1 <= m/2; e.nextprime(p1){ if ( e.faktorisering (m-p1).size() == 1 )) { // Funnet Goldbach sum break; } } // end p1 if (p1 > m/2) System.out.println( " BINGO: Funnet $1. mill:" + m + " kan ikke skrives som summen av to primtall "); } // end m Kan vi parallellisere inne i en parallellisering? Bør vi evt. gjøre det og hvorfor / hvorfor ikke? 45

Prog 1, finn én sum: n sekv(ms) para(ms) Speedup SekElem(us) ParaElem(us) EratosthesSil 2000000000 14872.89 7386.36 2.01 Goldbach Sum 2000000000 131447.23 31222.86 4.21 0.06572 0.01561 Total tid 2000000000 146350.58 38813.12 3.77 EratosthesSil 200000000 1156.82 336.60 3.44 Goldbach Sum 200000000 11224.35 2646.68 4.24 0.05612 0.01323 Total tid 200000000 12395.19 2990.45 4.14 EratosthesSil 20000000 69.13 29.94 2.31 Goldbach Sum 20000000 946.12 252.25 3.75 0.04731 0.01261 Total tid 20000000 1015.25 273.34 3.71 EratosthesSil 2000000 6.26 1.92 3.27 Goldbach Sum 2000000 81.11 18.89 4.29 0.04056 0.00945 Total tid 2000000 87.38 20.61 4.24 EratosthesSil 200000 0.56 0.40 1.38 Goldbach Sum 200000 6.84 2.90 2.36 0.03421 0.01452 Total tid 200000 7.42 3.30 2.25 EratosthesSil 20000 0.06 0.43 0.13 Goldbach Sum 20000 0.84 1.73 0.48 0.04187 0.08665 Total tid 20000 0.89 2.04 0.44 EratosthesSil 2000 0.01 0.36 0.03 Goldbach Sum 2000 0.35 1.81 0.19 0.17411 0.90483 Total tid 2000 0.36 2.17 0.17 46

Parallellisering av Oblig 3-1 Vi har en sekvensiell kode som virker. Vi har sannsynligvis da to metoder:. void sekrek(int p1, int p2, int p3, IntList p, IntList kohyll) linje p1-p2, (her f.eks. I-P) p3 er det punktet i mest negativ avstand fra p1-p2 (her C) p er mengden av punkter det søkes i kohyll er den mengden hvor punktene på kohyll noteres (i riktig rekkefølge). Den er deklarert og initiert tom før kallet og er svaret vårt 47

Parallellisering av Oblig3-2 int mestneg(int p1, int p2, IntList punktene, IntList nymengde) // finner nytt punkt mest til høyre for p1-p2 etter søk i punktene // nymengde = alle punkter i neg. avstand til p1-p2 i punktene Kalles to ganger fra sekrek først for p1-p3 og så for p3-p2. Hvordan parallelliserer vi dette? Bruker vi alle trådene over hver av de linjene vi rekursivt undersøker? Alle først på p1-p3, så alle på p3-p2, eller Halvparten på p1-p3 og andre halvpart på p3-p2 Hvordan syr vi sammen de delene av den konvekse innhyllinga vi finner? De svarene vi får når vi går over til sekvensiell rekursjon når trådene er brukt opp er greit i riktig rekkefølge, men hvordan med de punktene som finnes av trådene i tilfeldig rekkefølge. 48

Oblig 4 lagt ut nå Parallelliser Radix-sortering med to sifre Skriv rapport om speedup for n= 1000, 10 000, 100 000, 1 mill., 10 mill og 100 mill. Radix består av to metoder, begge skal parallelliseres. 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[] Steg a) er løst i ukeoppgave (hvor bla. hver tråd har sin kopi av count[]) 49

Den første av to algoritmer som 2-siffer Radix består av. radix2 radixsort radixsort // N.B. Sorterer a[] stigende antar at a[i] >=0 & max (a[i]) < 2 31 ) static void radix2(int [] a) { // 2 digit radixsort: a[] int max = a[0], numbit = 2, n =a.length; } // a1) finn max verdi i a[] for (int i = 1 ; i <= n ; i++) if (a[i] > max) max = a[i]; //a2) finn antall bit i max while (max >= (1<<numBit) )numbit++; // bestem antall bit i siffer1 og siffer2 int bit1 = numbit/2, bit2 = numbit-bit1; int[] b = new int [n]; radixsort( a,b, bit1, 0); // første siffer fra a[] til b[] radixsort( b,a, bit2, bit1);// andre siffer, tilbake fra b[] til a[] 50

radix2 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 = 0, j, n = a.length; int mask = (1<<maskLen) -1; int [] count = new int [mask+1]; // b) count=the frequency of each radix value in a for (int i= 0; i< n; i++) count[(a[i]>> shift) & mask]++; // c) Add up in 'count' - accumulated values for (int i = 0; i <= mask; i++) { j = count[i]; count[i] = acumval; acumval += j; } // d) move numbers in sorted order a to b for (int i= 0; i< n; i++) b[count[(a[i]>>shift) & mask]++] = a[i]; }// end radixsort 51

Hva så vi på i Uke11 I) En del sluttkommentarer og optimalisering av Oblig2 II) Debugging av parallelle programmer III) Et større problem uløst problem siden 1742 Vil du tjene 1 millioner $? Løs Goldbach s påstand (alternativt: motbevis den) Formulering og skisse av løsning av tre av Goldbachs problemer (Prog1, Prog2, Prog3) Parallellisering av disse (ukeoppgave neste uke) IV) Oblig 3 og 4 52