Java Laufzeitmessung rekursiv-nebenläufiger Programme

M

MiNeeMAL

Gast
PHP:
import java.util.Random;
import java.io.*;

@author amadeus p.  

public class mSort {
	
	/*sort wird überladen, damit beim späteren testen
	 * nur ein Array als Eingabe übergeben werden muss.
	 * */
	
	public static void sort(int[] a){
		
		sort(a,0, a.length-1);
		
	}
	
	//Eigentliche Implementation der Sortiermethode  
	 
	
	public static void sort(int[]a, int m, int n){
		int left = m;
		int right = n;
		int mid = (left+right)/2;
		int eleft = mid;
		int sright = mid+1;
		
		
		//Behandelt den Fall, dass es sich um ein 1-elementiges Array handelt
		if (left >= right){	
			return;
		}
		
		/*rekursiv-nebenläufiger Schritt!
		 */
		final int [] fa = a;
		final int fleft = left;
		final int fright = right;
		final int fmid = mid;

		
		
		
		Runnable lside = new Runnable(){
			public void run() {
				sort(fa, fleft, fmid);	
			}
		};
		
		Runnable rside = new Runnable(){
			public void run() {
				sort(fa, fmid+1, fright);
			}
		};
		
		new Thread(lside).start();
		new Thread(rside).start();
		
		while ((left <= eleft) && (sright <= right)){
			if (a[left] < a[sright]){
				left++;
			}	else {
				int tmp = a[sright];
				for (int k = sright - 1; k >= left; k--){
					a[k+1] = a[k];
				}
				
				a[left] = tmp;
				left++;
				eleft++;
				sright++;
				
			}
		}
	}
	

	public static int[] fillArray (int n){
		
		int[] a = new int[n];
		Random r = new Random();
		
		for (int k = 0; k<n; k++ ){
			a[k] = r.nextInt(1000);
		}
		
		return a;
	}
	

	public static void printArray (int[] a){
		for (int k = 0; k<a.length; k++){
			System.out.print(a[k]+" ");
		}
		System.out.println();
	}
	
	
	public static void main(String[] args) throws IOException{
		BufferedReader in = new BufferedReader (
							new InputStreamReader(System.in));
		
		System.out.println("Bitte Größe des zu generierenden Arrays eingeben: ");
		
		
		String gr = in.readLine();
		int gr2 = Integer.parseInt(gr);
		int [] test = fillArray(gr2);

		
		System.out.println();
		System.out.println("Unsortiertes Array");
		printArray(test);

		
		Long t1 = System.nanoTime();
		sort (test);
		Long t2 = (System.nanoTime()-t1);
		Long t3 = t2/(1000*1000);
		Long t4 = t3/1000;
		
		System.out.println("Sortiertes Array");
		printArray(test);
		
		System.out.println("Für den Sortiervorgang wurden " + t2 + " ns, " + t3 + " ms, bzw. ca. " + t4 + " s benötigt.");

	}
}

Nabend,

sitze im Moment an einer Aufgabe, bei der mittels nebenläufiger Rekursion der Mergesort-Algorithmus implementiert werden soll.

Soweit klappt auch alles, nur schaue ich beim Messen der Laufzeit etwas blöde in die Röhre. In der main-Methode wird ja die Laufzeit von sort() gemessen und die erstellt ja nur die zwei Threads und das war's. Danach spuckt mir die Konsole die Laufzeit aus und der Rechner ackert aber immernoch wie verrückt.

Anzumerken ist noch, dass die gemessene Laufzeit (fast) mit der sequenziell-rekursiven Variante übereinstimmt, was ja nicht stimmen kann.

Wie schaffe ich es denn, dass mir die korrekte Laufzeit ausgegeben wird?

Gruß
 
MiNeeMAL schrieb:
Anzumerken ist noch, dass die gemessene Laufzeit (fast) mit der sequenziell-rekursiven Variante übereinstimmt, was ja nicht stimmen kann.

Wie schaffe ich es denn, dass mir die korrekte Laufzeit ausgegeben wird?

Wie groß machst du die Arrays denn bei deinen Tests, und wird der Unterschied größer wenn du es deutlich vergrößerst?

Du musst auf das ende der Threads warten um die korrekte Zeit messen zu können. Das geht mit Thread.join()
 
Danke für den Hinweis ;)

Die Arrays bewegen sich in Größen zwischen 100.000 und 500.000 Elementen, die Messung soll aber auch für ein Maximum von 40.000.000 Elementen erfolgen.

Der Unterschied ist deutlich spürbar, da nicht nur der Prozessor stärker ausgelastet ist, sondern auch mein RAM randvoll ist (8 GB)
 
Sehe ich das richtig, daß du in jedem Rekursionsschritt zwei neue Threads erzeugst?

Das würde ich mir noch mal überlegen. Du handelst dir dadurch einen gewaltigen Overhead ein - sowohl an Speicher für die ganzen Objekte als auch an Rechenleistung für das Scheduling -, während du höchstens von so vielen Threads wirklich profitieren kannst, wie du Prozessorkerne hast.
 
NullPointer schrieb:
Sehe ich das richtig, daß du in jedem Rekursionsschritt zwei neue Threads erzeugst?

Das würde ich mir noch mal überlegen. Du handelst dir dadurch einen gewaltigen Overhead ein - sowohl an Speicher für die ganzen Objekte als auch an Rechenleistung für das Scheduling -, während du höchstens von so vielen Threads wirklich profitieren kannst, wie du Prozessorkerne hast.

Das ist wohl wahr. Man könnte entsprechende Kenntnisse vorausgesetzt einen festen Pool an Threads erstellen und die Aufgaben dorthin delegieren. Spontan fällt mir da das Kommando Pattern ein. In jedem Fall könnte man die Parameter für die sort() Funktion in ein Value Object kapseln und die Aufgaben in eine Queue (BlockingQueue für passives warten und Threadsicherheit) hängen.
 
Ich glaube du hast da auch noch ein paar Fehler in deinem Algorithmus... Zum einen musst du sicherstellen das der rekursive Zwischenschritt fertig ist bevor du mit dem mergen der Arrays beginnst und zum anderen kann der Mergealgorithmus so auch nicht funktionieren glaube ich.
 
Zurück
Oben