|
|
@@ -1,19 +1,31 @@ |
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
class MultiRadixPar{
|
|
|
|
import java.util.concurrent.CyclicBarrier;
|
|
|
|
/***********************************************************
|
|
|
|
* 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 MultiRadixPar implements Sorter {
|
|
|
|
int n;
|
|
|
|
volatile int[] a;
|
|
|
|
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);
|
|
|
|
16);
|
|
|
|
|
|
|
|
public int[] sort(int[] arr) {
|
|
|
|
return radixMulti(arr);
|
|
|
|
}
|
|
|
|
|
|
|
|
class PartAWorker implements Runnable {
|
|
|
|
int[] a;
|
|
|
|
int start;
|
|
|
|
int end;
|
|
|
|
int biggest;
|
|
|
|
|
|
|
|
PartAWorker(int start, int end) {
|
|
|
|
PartAWorker(int[] a, int start, int end) {
|
|
|
|
this.a = a;
|
|
|
|
this.start = start;
|
|
|
|
this.end = end;
|
|
|
|
this.biggest = a[start];
|
|
|
@@ -27,33 +39,30 @@ class MultiRadixPar{ |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int [] radixMulti(int [] a_) {
|
|
|
|
this.a = a_;
|
|
|
|
nThreads = 2;
|
|
|
|
|
|
|
|
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();
|
|
|
|
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));
|
|
|
|
a, d * i, i == nThreads - 1 ? a.length : d * (i + 1));
|
|
|
|
|
|
|
|
Thread t = threads[i] = new Thread(w);
|
|
|
|
t.start();
|
|
|
|
}
|
|
|
|
for (int i = 0; i < nThreads; ++i) {
|
|
|
|
try { threads[i].join(); } catch (InterruptedException ex) {}
|
|
|
|
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);
|
|
|
@@ -69,89 +78,144 @@ class MultiRadixPar{ |
|
|
|
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[]
|
|
|
|
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 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;
|
|
|
|
class Worker extends Thread {
|
|
|
|
int index;
|
|
|
|
CyclicBarrier barrier;
|
|
|
|
int[] a;
|
|
|
|
int[] b;
|
|
|
|
int[][] accumulated;
|
|
|
|
int[] globalCount;
|
|
|
|
int[][] count2d;
|
|
|
|
int mask;
|
|
|
|
int shift;
|
|
|
|
int start;
|
|
|
|
int end;
|
|
|
|
boolean doD = false;
|
|
|
|
|
|
|
|
int acumVal;
|
|
|
|
int j;
|
|
|
|
int[] count;
|
|
|
|
|
|
|
|
Worker(
|
|
|
|
int index, CyclicBarrier barrier,
|
|
|
|
int[] a, int[] b, int[][] accumulated,
|
|
|
|
int[] globalCount, int[][] count2d,
|
|
|
|
int mask, int shift,
|
|
|
|
int start, int end) {
|
|
|
|
|
|
|
|
this.index = index;
|
|
|
|
this.barrier = barrier;
|
|
|
|
this.a = a;
|
|
|
|
this.b = b;
|
|
|
|
this.count = new int[mask + 1];
|
|
|
|
this.shift = shift;
|
|
|
|
this.accumulated = accumulated;
|
|
|
|
this.globalCount = globalCount;
|
|
|
|
this.count2d = count2d;
|
|
|
|
this.mask = mask;
|
|
|
|
}
|
|
|
|
this.shift = shift;
|
|
|
|
this.start = start;
|
|
|
|
this.end = end;
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
acumVal = 0;
|
|
|
|
j = 0;
|
|
|
|
count = new int[mask+1];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
synchronized public void run() {
|
|
|
|
// 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;
|
|
|
|
for (int i = start; i < end; 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();
|
|
|
|
int j = 0;
|
|
|
|
int acumVal = 0;
|
|
|
|
for (int i = 0; i <= mask; i++) {
|
|
|
|
count2d[index][i] = count[i];
|
|
|
|
j = count[i];
|
|
|
|
count[i] = acumVal;
|
|
|
|
accumulated[index][i] = acumVal;
|
|
|
|
acumVal += j;
|
|
|
|
}
|
|
|
|
System.out.println("C: "+tc.end().prettyTime());
|
|
|
|
|
|
|
|
// d)
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
int var = (a[i] >>> shift) & mask;
|
|
|
|
if (var >= start && var < end) {
|
|
|
|
b[count[var]++] = a[i];
|
|
|
|
// Wait for synchronization
|
|
|
|
try { barrier.await(); } catch (Exception ex) {}
|
|
|
|
while (!doD)
|
|
|
|
try { wait(); } catch (InterruptedException ex) {}
|
|
|
|
|
|
|
|
// d) move numbers in sorted order a to b
|
|
|
|
int[] space = new int[mask + 1];
|
|
|
|
for (int i = 0; i < mask + 1; ++i) {
|
|
|
|
for (int j = 0; j < index; ++j) {
|
|
|
|
space[i] += count2d[j][i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
for (int i = start; i < end; i++) {
|
|
|
|
int idx = (a[i] >>> shift) & mask;
|
|
|
|
b[globalCount[idx] + space[idx]++] = a[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
synchronized public void startPartD() {
|
|
|
|
this.doD = true;
|
|
|
|
notify();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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];
|
|
|
|
|
|
|
|
/*
|
|
|
|
Timer td = new Timer().start();
|
|
|
|
int d = biggestVar / nThreads;
|
|
|
|
Thread[] threads = new Thread[nThreads];
|
|
|
|
void radixSort ( int [] a, int [] b, int maskLen, int shift){
|
|
|
|
int mask = (1 << maskLen) - 1;
|
|
|
|
|
|
|
|
CyclicBarrier barrier = new CyclicBarrier(nThreads + 1);
|
|
|
|
int[][] accumulated = new int[nThreads][mask + 1];
|
|
|
|
int[][] count2d = new int[nThreads][mask + 1];
|
|
|
|
int[] count = new int[mask + 1];
|
|
|
|
|
|
|
|
// Create and start workers
|
|
|
|
Worker[] workers = new Worker[nThreads];
|
|
|
|
int d = a.length / nThreads;
|
|
|
|
for (int i = 0; i < nThreads; ++i) {
|
|
|
|
int start = d * i;
|
|
|
|
int end = i == nThreads - 1 ? n + 1 : d * (i + 1);
|
|
|
|
int end = i == nThreads - 1 ? a.length : d * (i + 1);
|
|
|
|
workers[i] = new Worker(
|
|
|
|
i, barrier,
|
|
|
|
a, b, accumulated,
|
|
|
|
count, count2d,
|
|
|
|
mask, shift,
|
|
|
|
start, end);
|
|
|
|
workers[i].start();
|
|
|
|
}
|
|
|
|
|
|
|
|
PartDWorker w = new PartDWorker(start, end, b, count, shift, mask);
|
|
|
|
Thread t = threads[i] = new Thread(w);
|
|
|
|
t.start();
|
|
|
|
// Synchronize
|
|
|
|
try { barrier.await(); } catch (Exception ex) {}
|
|
|
|
|
|
|
|
// Sequentially fix count
|
|
|
|
for (int i=0; i < count.length; ++i) {
|
|
|
|
for (int j = 0; j < nThreads; ++j) {
|
|
|
|
count[i] += accumulated[j][i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do part D
|
|
|
|
for (Worker w: workers) {
|
|
|
|
w.startPartD();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Thread t: threads) {
|
|
|
|
try { t.join(); } catch (InterruptedException ex) {}
|
|
|
|
// Join threads
|
|
|
|
for (int i = 0; i < nThreads; ++i) {
|
|
|
|
try { workers[i].join(); } catch (InterruptedException ex) {}
|
|
|
|
}
|
|
|
|
System.out.println("par D: "+td.end().prettyTime());
|
|
|
|
*/
|
|
|
|
}// end radixSort
|
|
|
|
|
|
|
|
void testSort(int [] a){
|