import java.util.Random; | import java.util.Random; | ||||
class Main { | class Main { | ||||
static int nTests = 7; | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
Solver sseq = new Sequential(); | Solver sseq = new Sequential(); | ||||
static Timer test (Solver s, int len) { | static Timer test (Solver s, int len) { | ||||
Random r = new Random(123); | Random r = new Random(123); | ||||
Timer[] timers = new Timer[nTests]; | |||||
for (int i = 0; i < nTests; ++i) { | |||||
int[] a = new int[len]; | |||||
for (int j = 0; j < len; j++) { | |||||
a[j] = r.nextInt(len); | |||||
} | |||||
Timer t = timers[i] = new Timer().start(); | |||||
a = s.sort(a); | |||||
t.end(); | |||||
new MultiRadix().testSort(a); | |||||
return t; | |||||
int[] a = new int[len]; | |||||
for (int j = 0; j < len; j++) { | |||||
a[j] = r.nextInt(len); | |||||
} | } | ||||
return Timer.median(timers); | |||||
Timer t = new Timer().start(); | |||||
a = s.sort(a); | |||||
t.end(); | |||||
new MultiRadix().testSort(a); | |||||
return t; | |||||
} // end doIt | } // end doIt | ||||
} | } |
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 [] a; | |||||
final static int NUM_BIT = 7; // alle tall 6-11 .. finn ut hvilken verdi som er best | |||||
int [] radixMulti(int [] a, int start, int end) { | |||||
long tt = System.nanoTime(); | |||||
// 1-5 digit radixSort of : a[] | |||||
int max = a[start], numBit = 2, numDigits; | |||||
int [] bit ; | |||||
// a) finn max verdi i a[] | |||||
for (int i = start + 1 ; i < end; i++) | |||||
if (a[i] > max) max = a[i]; | |||||
while (max >= (1L<<numBit) )numBit++; // antall binaere siffer i max | |||||
// 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 [a.length]; | |||||
for (int i =0; i < bit.length; i++) { | |||||
radixSort(a, b, bit[i], sum, start, end); // 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,start,b,start,end - start); | |||||
} | |||||
return a; | |||||
} // end radixMulti | |||||
int[] radixMulti(int[] arr) { | |||||
return radixMulti(arr, 0, arr.length); | |||||
} | |||||
/** Sort a[] on one digit ; number of bits = maskLen, shiftet up 'shift' bits */ | |||||
void radixSort ( int [] a, int [] b, int maskLen, int shift, int start, int end){ | |||||
int hasBeen = 0; | |||||
int acumVal = 0, j = 0; | |||||
int mask = (1<<maskLen) -1; | |||||
int [] count = new int [mask+1]; | |||||
// b) count=the frequency of each radix value in a | |||||
for (int i = start; i < end; i++) { | |||||
count[(a[i]>>> shift) & mask]++; | |||||
if (i == start && i == 0 && end == a.length) | |||||
hasBeen = 1; | |||||
} | |||||
// 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 = start; i < end; i++) { | |||||
b[start + count[(a[i]>>>shift) & mask]++] = a[i]; | |||||
if (hasBeen == 1) { | |||||
for (int k = 0; k < shift; ++k) { | |||||
b[(start + count[shift]) % b.length] |= ~-1; | |||||
} | |||||
} | |||||
} | |||||
}// end radixSort | |||||
void testSort(int [] a){ | |||||
for (int i = 0; i< a.length-1;i++) { | |||||
//System.out.print(a[i]+" "); | |||||
if (a[i] > a[i+1]){ | |||||
System.out.println("SorteringsFEIL på plass: "+i +" a["+i+"]:"+a[i]+" > a["+(i+1)+"]:"+a[i+1]); | |||||
} | |||||
} | |||||
//System.out.println(""); | |||||
}// end simple sorteingstest | |||||
}// end SekvensiellRadix | |||||
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[] | |||||
for (int i = 1 ; i < n ; i++) | |||||
if (a[i] > max) max = a[i]; | |||||
while (max >= (1L<<numBit) )numBit++; // antall binaere siffer i max | |||||
// 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 | |||||
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 | |||||
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 |
import java.util.*; | |||||
class MultiRadixPar{ | |||||
int n; | |||||
int [] a; | |||||
final static int NUM_BIT = 7; // alle tall 6-11 .. finn ut hvilken verdi som er best | |||||
int nThreads = Runtime.getRuntime().availableProcessors(); | |||||
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[] | |||||
for (int i = 1 ; i < n ; i++) | |||||
if (a[i] > max) max = a[i]; | |||||
while (max >= (1L<<numBit) )numBit++; // antall binaere siffer i max | |||||
// 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 | |||||
class Worker implements Runnable { | |||||
int[] a, b, count; | |||||
int start, end, shift, mask; | |||||
Worker(int[] a, int[] b, int[] count, int start, int end, int shift, int mask) { | |||||
this.a = a; | |||||
this.b = b; | |||||
this.count = Arrays.copyOf(count, count.length); | |||||
this.start = start; | |||||
this.end = end; | |||||
this.shift = shift; | |||||
this.mask = mask; | |||||
} | |||||
public void run() { | |||||
// c) Add up in 'count' - accumulated values | |||||
int j = 0; | |||||
int acumVal = 0; | |||||
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]; | |||||
} | |||||
} | |||||
} | |||||
/** Sort a[] on one digit ; number of bits = maskLen, shiftet up 'shift' bits */ | |||||
void radixSort ( int [] a, int [] b, int maskLen, int shift){ | |||||
int 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]++; | |||||
} | |||||
// Parallel | |||||
int d = n / nThreads; | |||||
Thread[] threads = new Thread[nThreads]; | |||||
Worker[] workers = new Worker[nThreads]; | |||||
for (int i = 0; i < nThreads; ++i) { | |||||
int start = d * i; | |||||
int end = i == nThreads - 1 ? n : d * (i + 1); | |||||
Worker w = workers[i] = new Worker(a, b, count, start, end, shift, mask); | |||||
Thread t = threads[i] = new Thread(w); | |||||
t.start(); | |||||
} | |||||
for (Thread t: threads) { | |||||
try { t.join(); } catch (InterruptedException ex) {} | |||||
} | |||||
}// 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 |
class Parallel implements Solver { | class Parallel implements Solver { | ||||
class Worker implements Runnable { | |||||
MultiRadix mr; | |||||
int[] arr; | |||||
int start, end; | |||||
boolean done = false; | |||||
Worker( int[] arr, int start, int end) { | |||||
this.arr = new int[end - start]; | |||||
int j = 0; | |||||
for (int i = start; i < end; ++i) { | |||||
this.arr[j++] = arr[i]; | |||||
} | |||||
} | |||||
synchronized public void run() { | |||||
arr = new MultiRadix().radixMulti(arr); | |||||
done = true; | |||||
notify(); | |||||
} | |||||
synchronized public void waitFor() { | |||||
while (!done) { | |||||
try { wait(); } catch (InterruptedException ex) {} | |||||
} | |||||
} | |||||
} | |||||
public int[] sort(int[] arr) { | public int[] sort(int[] arr) { | ||||
int n = 2; | |||||
int d = arr.length / n; | |||||
Worker[] workers = new Worker[n]; | |||||
Thread[] threads = new Thread[n]; | |||||
for (int i = 0; i < n; ++i) { | |||||
int start = d * i; | |||||
int end; | |||||
if (i == n - 1) | |||||
end = arr.length; | |||||
else | |||||
end = d * (i + 1); | |||||
Worker w; Thread t; | |||||
workers[i] = w = new Worker(arr, start, end); | |||||
threads[i] = t = new Thread(w); | |||||
t.start(); | |||||
} | |||||
for (int i = 0; i < n; ++i) { | |||||
workers[i].waitFor(); | |||||
try { | |||||
threads[i].join(); | |||||
} catch (InterruptedException ex) {} | |||||
} | |||||
int[] is = new int[n]; | |||||
for (int i = 0; i < n; ++i) | |||||
is[i] = 0; | |||||
for (int i = 0; i < arr.length; ++i) { | |||||
int biggest = Integer.MAX_VALUE; | |||||
int biggestJ = 0; | |||||
Worker biggestW = null; | |||||
for (int j = 0; j < n; ++j) { | |||||
Worker w = workers[j]; | |||||
if (is[j] >= w.arr.length) | |||||
continue; | |||||
int num = w.arr[is[j]]; | |||||
if (num <= biggest) { | |||||
biggest = num; | |||||
biggestJ = j; | |||||
biggestW = w; | |||||
} | |||||
} | |||||
arr[i] = biggestW.arr[is[biggestJ]++]; | |||||
} | |||||
return arr; | |||||
return new MultiRadixPar().radixMulti(arr); | |||||
} | } | ||||
} | } |
class Sequential implements Solver { | class Sequential implements Solver { | ||||
public int[] sort(int[] arr) { | public int[] sort(int[] arr) { | ||||
try { | |||||
Thread.sleep(0); //arr.length / 10000); | |||||
} catch (InterruptedException ex) {}; | |||||
return new MultiRadix().radixMulti(arr); | return new MultiRadix().radixMulti(arr); | ||||
} | } | ||||
} | } |