Hallo,
ich implementiere zur Zeit einen Mergesort, welcher mit Threads zum Teil paralellisiert werden soll. Dabei achte ich darauf, dass nie mehr als eine bestimmte Anzahl an Threads gespawnt werden.
Hier ist das was ich mir überlegt habe:
Ich bemerke, dass ich bei erst ca. 2mio+ Elemente einen Speedup habe. Meine Frage ist nun, kann ich dieses Code eventuell noch optimieren?
mfg Timo
ich implementiere zur Zeit einen Mergesort, welcher mit Threads zum Teil paralellisiert werden soll. Dabei achte ich darauf, dass nie mehr als eine bestimmte Anzahl an Threads gespawnt werden.
Hier ist das was ich mir überlegt habe:
Java:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MergesortConcurrentLimited implements Sort{
private static final int nThreads = Runtime.getRuntime().availableProcessors();
private int threads = 1; //Startet mit 1, da wir einen root thread haben
private Lock lock = new ReentrantLock();
@Override
public void sort(int[] array) {
try {
int [] tmp = new int[array.length]; //Wir arbeiten mit einem Hilfsarray, das mitgereicht wird
Mergesorter root = new Mergesorter(array,tmp,0,array.length-1);
root.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
private void mergesort(int[] array, int[] tmp, int lower, int upper) {
if (lower < upper) {
int pivot = (lower + upper) / 2;
try {
Mergesorter m1 = null;
Mergesorter m2 = null;
/* Es wird überprüft, ob wir einen neuen Thread spawnen können.
* Nur möglich, wenn kritischer Abschnitt freigegeben ist, bzw. weniger als nThreads laufen.
* Ansonsten rufen wir mergesort imperativ auf. (Das ganze für linke bzw. rechte) Teilliste
*/
if(threads < nThreads && lock.tryLock()){
try{
m1 = new Mergesorter(array,tmp,lower,pivot);
threads += 1;
}finally{
lock.unlock();
}
}else{
mergesort(array,tmp,lower,pivot);
}
if(threads < nThreads && lock.tryLock()){
try{
m2 = new Mergesorter(array, tmp, pivot + 1, upper);
threads += 1;
}finally{
lock.unlock();
}
}else{
mergesort(array, tmp, pivot + 1, upper);
}
if(m1 != null){
m1.join();
}
if(m2 != null){
m2.join();
}
} catch (Exception ex) {
ex.printStackTrace();
}
merge(array, tmp, lower, pivot, upper);
}
}
private void merge(int[] array,int[] tmp, int lower, int pivot, int upper){
System.arraycopy(array, lower, tmp, lower, upper - lower + 1);
int left = lower, right = pivot+1, i = lower;
while(left <= pivot && right <= upper){
if(tmp[left] <= tmp[right]){
array[i] = tmp[left];
left++;
}else{
array[i] = tmp[right];
right++;
}
i++;
}
System.arraycopy(tmp, left, array, i, pivot-left+1);
}
private class Mergesorter implements Runnable{
private int[] array,helper;
private int lower,upper;
private Thread thread;
public Mergesorter(int[] array, int[] helper, int lower, int upper){
this.array = array;
this.helper = helper;
this.lower = lower;
this.upper = upper;
thread = new Thread(this);
thread.start();
}
@Override
public void run() {
mergesort(array,helper,lower,upper);
}
public void join() throws InterruptedException{
thread.join();
threads -= 1;
}
}
}
Ich bemerke, dass ich bei erst ca. 2mio+ Elemente einen Speedup habe. Meine Frage ist nun, kann ich dieses Code eventuell noch optimieren?
mfg Timo