@@ -1,36 +0,0 @@ | |||
import java.util.Random; | |||
class Main { | |||
public static void main(String[] args) { | |||
Solver sseq = new Sequential(); | |||
Solver spar = new Parallel(); | |||
if (args.length != 1) { | |||
System.out.println(" bruk : >java SekvensiellRadix <n> "); | |||
} else { | |||
int n = Integer.parseInt(args[0]); | |||
Timer seq = test(sseq, n); | |||
System.out.println("Sequential: "+seq.prettyTime()); | |||
Timer par = test(spar, n); | |||
System.out.println("Parallel: "+par.prettySpeedup(seq)); | |||
} | |||
} | |||
static Timer test (Solver s, int len) { | |||
Random r = new Random(123); | |||
int[] a = new int[len]; | |||
for (int j = 0; j < len; j++) { | |||
a[j] = r.nextInt(len); | |||
} | |||
Timer t = new Timer().start(); | |||
a = s.sort(a); | |||
t.end(); | |||
new MultiRadix().testSort(a); | |||
return t; | |||
} // end doIt | |||
} |
@@ -1,95 +0,0 @@ | |||
import java.util.*; | |||
/*********************************************************** | |||
* Oblig 3 - sekvensiell kode, INF2440 v2017. | |||
* Ifi, Uio, Arne Maus | |||
* for store verdier av n > 100 m, kjør (f.eks): | |||
* >java -Xmx16000m MultiRadix 1000000000 | |||
************************************************************/ | |||
class MultiRadix{ | |||
int n; | |||
int [] a; | |||
final static int NUM_BIT = 7; // alle tall 6-11 .. finn ut hvilken verdi som er best | |||
int [] radixMulti(int [] a) { | |||
long tt = System.nanoTime(); | |||
// 1-5 digit radixSort of : a[] | |||
int max = a[0], numBit = 2, numDigits, n =a.length; | |||
int [] bit ; | |||
// a) finn max verdi i a[] | |||
//Timer ta = new Timer().start(); | |||
for (int i = 1 ; i < n ; i++) | |||
if (a[i] > max) max = a[i]; | |||
while (max >= (1L<<numBit) )numBit++; // antall binaere siffer i max | |||
//System.out.println("A: "+ta.end().prettyTime()); | |||
// bestem antall bit i numBits sifre | |||
numDigits = Math.max(1, numBit/NUM_BIT); | |||
bit = new int[numDigits]; | |||
int rest = (numBit%numDigits), sum =0;; | |||
// fordel bitene vi skal sortere paa jevnt | |||
for (int i = 0; i < bit.length; i++){ | |||
bit[i] = numBit/numDigits; | |||
if ( rest-- > 0) bit[i]++; | |||
} | |||
int[] t=a, b = new int [n]; | |||
for (int i =0; i < bit.length; i++) { | |||
radixSort( a,b,bit[i],sum ); // i-te siffer fra a[] til b[] | |||
sum += bit[i]; | |||
// swap arrays (pointers only) | |||
t = a; | |||
a = b; | |||
b = t; | |||
} | |||
if (bit.length%2 != 0 ) { | |||
// et odde antall sifre, kopier innhold tilbake til original a[] (nå b) | |||
System.arraycopy (a,0,b,0,a.length); | |||
} | |||
return a; | |||
} // end radixMulti | |||
/** Sort a[] on one digit ; number of bits = maskLen, shiftet up 'shift' bits */ | |||
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 | |||
//Timer tb = new Timer().start(); | |||
for (int i = 0; i < n; i++) { | |||
count[(a[i]>>> shift) & mask]++; | |||
} | |||
//System.out.println("B: "+tb.end().prettyTime()); | |||
// c) Add up in 'count' - accumulated values | |||
//Timer tc = new Timer().start(); | |||
for (int i = 0; i <= mask; i++) { | |||
j = count[i]; | |||
count[i] = acumVal; | |||
acumVal += j; | |||
} | |||
//System.out.println("C: "+tc.end().prettyTime()); | |||
// d) move numbers in sorted order a to b | |||
//Timer t = new Timer().start(); | |||
for (int i = 0; i < n; i++) { | |||
b[count[(a[i]>>>shift) & mask]++] = a[i]; | |||
} | |||
//t.end(); | |||
//System.out.println("seq D: "+t.prettyTime()); | |||
}// end radixSort | |||
void testSort(int [] a){ | |||
for (int i = 0; i< a.length-1;i++) { | |||
if (a[i] > a[i+1]){ | |||
System.out.println("SorteringsFEIL på plass: "+i +" a["+i+"]:"+a[i]+" > a["+(i+1)+"]:"+a[i+1]); | |||
return; | |||
} | |||
} | |||
}// end simple sorteingstest | |||
}// end SekvensiellRadix |
@@ -1,164 +0,0 @@ | |||
import java.util.*; | |||
class MultiRadixPar{ | |||
int n; | |||
volatile int[] a; | |||
final static int NUM_BIT = 7; // alle tall 6-11 .. finn ut hvilken verdi som er best | |||
int nThreads = Math.min( | |||
Runtime.getRuntime().availableProcessors(), | |||
8); | |||
class PartAWorker implements Runnable { | |||
int start; | |||
int end; | |||
int biggest; | |||
PartAWorker(int start, int end) { | |||
this.start = start; | |||
this.end = end; | |||
this.biggest = a[start]; | |||
} | |||
public void run() { | |||
for (int i = start + 1; i < end; ++i) { | |||
if (a[i] > biggest) | |||
biggest = a[i]; | |||
} | |||
} | |||
} | |||
int [] radixMulti(int [] a_) { | |||
this.a = a_; | |||
// 1-5 digit radixSort of : a[] | |||
int max = a[0], numBit = 2, numDigits, n =a.length; | |||
int [] bit ; | |||
// a) finn max verdi i a[] | |||
//Timer ta = new Timer().start(); | |||
int d = a.length / nThreads; | |||
Thread[] threads = new Thread[nThreads]; | |||
PartAWorker[] workers = new PartAWorker[nThreads]; | |||
for (int i = 0; i < nThreads; ++i) { | |||
PartAWorker w = workers[i] = new PartAWorker( | |||
d * i, i == nThreads - 1 ? a.length : d * (i + 1)); | |||
Thread t = threads[i] = new Thread(w); | |||
t.start(); | |||
} | |||
for (Thread t: threads) { try { t.join(); } catch (InterruptedException ex) {} } | |||
max = workers[0].biggest; | |||
for (int i = 1; i < nThreads; ++i) { | |||
if (workers[i].biggest > max) | |||
max = workers[i].biggest; | |||
} | |||
while (max >= (1L<<numBit) )numBit++; // antall binaere siffer i max | |||
//System.out.println("A: "+ta.end().prettyTime()); | |||
// bestem antall bit i numBits sifre | |||
numDigits = Math.max(1, numBit/NUM_BIT); | |||
bit = new int[numDigits]; | |||
int rest = (numBit%numDigits), sum =0;; | |||
// fordel bitene vi skal sortere paa jevnt | |||
for (int i = 0; i < bit.length; i++){ | |||
bit[i] = numBit/numDigits; | |||
if ( rest-- > 0) bit[i]++; | |||
} | |||
int[] t=a, b = new int [n]; | |||
for (int i =0; i < bit.length; i++) { | |||
radixSort( b,bit[i],sum ); // i-te siffer fra a[] til b[] | |||
sum += bit[i]; | |||
// swap arrays (pointers only) | |||
t = a; | |||
a = b; | |||
b = t; | |||
} | |||
if (bit.length%2 == 0 ) { | |||
// et odde antall sifre, kopier innhold tilbake til original a[] (nå b) | |||
System.arraycopy (b,0,a,0,a.length); | |||
} | |||
return a; | |||
} // end radixMulti | |||
class PartDWorker implements Runnable { | |||
int start, end, shift, mask; | |||
int[] b, count; | |||
PartDWorker(int start, int end, int[] b, int[] count, int shift, int mask) { | |||
this.start = start; | |||
this.end = end; | |||
this.b = b; | |||
this.count = count; | |||
this.shift = shift; | |||
this.mask = mask; | |||
} | |||
public void run() { | |||
for (int i = 0; i < n; i++) { | |||
int var = (a[i] >>> shift) & mask; | |||
if (var >= start && var < end) { | |||
b[count[var]++] = a[i]; | |||
} | |||
} | |||
} | |||
} | |||
/** Sort a[] on one digit ; number of bits = maskLen, shiftet up 'shift' bits */ | |||
void radixSort (int [] b, int maskLen, int shift){ | |||
int n = a.length; | |||
int mask = (1<<maskLen) -1; | |||
int [] count = new int [mask+1]; | |||
int biggestVar = 0; | |||
// b) count=the frequency of each radix value in a | |||
//Timer tb = new Timer().start(); | |||
for (int i = 0; i < n; i++) { | |||
int var = (a[i]>>>shift) & mask; | |||
count[var]++; | |||
if (var > biggestVar) | |||
biggestVar = var; | |||
} | |||
//System.out.println("B: "+tb.end().prettyTime()); | |||
// c) Add up in 'count' - accumulated values | |||
//Timer tc = new Timer().start(); | |||
int j = 0; | |||
int acumVal = 0; | |||
for (int i = 0; i <= mask; i++) { | |||
j = count[i]; | |||
count[i] = acumVal; | |||
acumVal += j; | |||
} | |||
//System.out.println("C: "+tc.end().prettyTime()); | |||
//Timer td = new Timer().start(); | |||
int d = biggestVar / nThreads; | |||
Thread[] threads = new Thread[nThreads]; | |||
for (int i = 0; i < nThreads; ++i) { | |||
int start = d * i; | |||
int end = i == nThreads - 1 ? n + 1 : d * (i + 1); | |||
PartDWorker w = new PartDWorker(start, end, b, count, shift, mask); | |||
Thread t = threads[i] = new Thread(w); | |||
t.start(); | |||
} | |||
for (Thread t: threads) { | |||
try { t.join(); } catch (InterruptedException ex) {} | |||
} | |||
//System.out.println("par D: "+td.end().prettyTime()); | |||
}// end radixSort | |||
void testSort(int [] a){ | |||
for (int i = 0; i< a.length-1;i++) { | |||
if (a[i] > a[i+1]){ | |||
System.out.println("SorteringsFEIL på plass: "+i +" a["+i+"]:"+a[i]+" > a["+(i+1)+"]:"+a[i+1]); | |||
return; | |||
} | |||
} | |||
}// end simple sorteingstest | |||
}// end SekvensiellRadix |
@@ -1,5 +0,0 @@ | |||
class Parallel implements Solver { | |||
public int[] sort(int[] arr) { | |||
return new MultiRadixPar().radixMulti(arr); | |||
} | |||
} |
@@ -1,5 +0,0 @@ | |||
class Sequential implements Solver { | |||
public int[] sort(int[] arr) { | |||
return new MultiRadix().radixMulti(arr); | |||
} | |||
} |
@@ -1,3 +0,0 @@ | |||
interface Solver { | |||
int[] sort(int[] a); | |||
} |
@@ -1,60 +0,0 @@ | |||
import java.util.Arrays; | |||
class Timer implements Comparable<Timer> { | |||
public long time = 0; | |||
private long start = 0; | |||
Timer() {} | |||
Timer(long time) { | |||
this.time = time; | |||
} | |||
public Timer start() { | |||
start = System.nanoTime(); | |||
return this; | |||
} | |||
public Timer end() { | |||
time = System.nanoTime() - start; | |||
return this; | |||
} | |||
public String prettyTime() { | |||
if (time < 1000) | |||
return String.format("%.2fns", time / 1f); | |||
else if (time < 1000000) | |||
return String.format("%.2fμs", time / 1000f); | |||
else if (time < 1000000000) | |||
return String.format("%.2fms", time / 1000000f); | |||
else | |||
return String.format("%.2fs", time / 1000000000f); | |||
} | |||
public String prettySpeedup(Timer base) { | |||
double speedup = (double)base.time / (double)time; | |||
return String.format("%s (%.2fx speedup)", | |||
prettyTime(), speedup); | |||
} | |||
public static Timer median(Timer[] timers) { | |||
Arrays.sort(timers); | |||
Timer med = new Timer(); | |||
int mid = timers.length / 2; | |||
if (timers.length % 2 == 0) | |||
med.time = (timers[mid].time + timers[mid+1].time) / 2; | |||
else | |||
med.time = timers[mid].time; | |||
return med; | |||
} | |||
public int compareTo(Timer t) { | |||
if (this.time < t.time) | |||
return -1; | |||
else if (this.time > t.time) | |||
return 1; | |||
else | |||
return 0; | |||
} | |||
} |
@@ -1,3 +0,0 @@ | |||
martin@elli:~/tmp$ java Main 200000000 | |||
Sequential: 4.99s | |||
Parallel: 2.11s (2.37x speedup) |
@@ -1,40 +0,0 @@ | |||
Kompilering: `javac *.java` | |||
Kjøring: `java Main <tall>` | |||
# Eksempelutskrift | |||
I filen output.txt finner du et eksempel på å kjøre `java Main 2000000000`. | |||
# Tider | |||
CPU: quad core Intel Xeon E31225 @ 3.1 GHz (ingen hyperthreading) | |||
200 000 000: | |||
* Sekvensiell: 4.99s | |||
* Parallell: 2.11s (2.37x speedup) | |||
20 000 000: | |||
* Sekvensiell: 257.75ms | |||
* Parallell: 186.53ms (1.48x speedup) | |||
2 000 000: | |||
* Sekvensiell: 54.04ms | |||
* Parallell: 44.87 (1.20x speedup) | |||
200 000: | |||
* Sekvensiell: 22.94ms | |||
* Parallell: 12.46ms (1.84x speedup) | |||
20 000: | |||
* Sekvensiell: 3.87ms | |||
* Parallell: 4.54ms (0.85x speedup) | |||
2 000: | |||
* Sekvensiell:895.36μs | |||
* Parallell: 2.68ms (0.33x speedup) | |||
## Del C | |||
Jeg skjønte ikke helt grunnen til å paralellisere del C. I mine tester tar C | |||
mikrosekunder, så det ville tatt lengre tid å spawne trådene enn å bare | |||
gjøre det sekvensielt?? |