/* * mergesort using data generated by RNG. * * parallel version using Java. * * command-line arguments specify number of elements to sort, seed for RNG, * number of threads. */ package csci3366.sample.mergesort; import csci3366.sample.utility.Utility; import java.util.Random; public class MergeSortPar { /* main method */ public static void main(String[] args) { String usageMessage = "arguments: numElements seed numThreads"; /* process command-line arguments */ int n = Utility.getIntegerArg(args, 0, 1, "numElements", usageMessage); int seed = Utility.getIntegerArg(args, 1, 1, "seed", usageMessage); int numThreads = Utility.getIntegerArg(args, 2, 1, "numThreads", usageMessage); /* generate data */ Integer[] ints = new Integer[n]; Random randGen = new Random((long) seed); for (int i = 0; i < ints.length; ++i) { ints[i] = new Integer(randGen.nextInt()); } /* sort (time this part only) */ long startTime = System.currentTimeMillis(); ints = sort(ints, numThreads); long endTime = System.currentTimeMillis(); /* print parameters */ System.out.println("Parallel mergesort of " + n + " random integers (seed " + seed + ")" + " with " + numThreads + " threads"); /* check whether sort succeeded */ if (isSorted(ints)) { System.out.println("Sort succeeded"); } else { System.out.println("Sort failed"); } /* print timing result */ System.out.println("Time " + ((double) (endTime - startTime) / 1000) + " seconds"); } /* check whether array is sorted */ public static boolean isSorted(Integer[] data) { for (int i = 0; i < data.length-1; ++i) { if (data[i].compareTo(data[i+1]) > 0) return false; } return true; } /* main mergesort routine */ public static Integer[] sort(Integer[] data, int numThreads) { Integer[] temp = mergesort(data, 0, data.length-1, numThreads); return temp; } /* * recursive mergesort: * sorts data[firstIndex..lastIndex] using numThreads threads * and returns result (in a new array) */ private static Integer[] mergesort(Integer[] data, int firstIndex, int lastIndex, int numThreads) { if (firstIndex > lastIndex) { return new Integer[0]; } else if (firstIndex == lastIndex) { return new Integer[] { data[firstIndex] }; } int midIndex = (firstIndex + lastIndex) / 2; Integer[] temp1 = null; Thread otherThread = null; CodeForThread other = null; /* sort left half of array */ if (numThreads > 1) { /* fork off a thread to do one of the mergesorts */ other = new CodeForThread(data, firstIndex, midIndex, numThreads/2);; otherThread = new Thread(other); otherThread.start(); } else { /* sort in same thread */ temp1 = mergesort(data, firstIndex, midIndex, numThreads/2); } /* sort right half of array */ Integer[] temp2 = mergesort(data, midIndex+1, lastIndex, numThreads-(numThreads/2)); if (numThreads > 1) { /* wait for other thread to finish */ try { otherThread.join(); } catch (InterruptedException e) { System.out.println("this should not happen"); } temp1 = other.getResult(); } /* merge two sorted arrays */ return merge(temp1, temp2); } /* merge sorted arrays a1, a2, and return result */ private static Integer[] merge(Integer[] a1, Integer[] a2) { Integer[] result = new Integer[a1.length + a2.length]; int i1 = 0; /* index into a1 */ int i2 = 0; /* index into a2 */ for (int j = 0; j < result.length; ++j) { if (i2 >= a2.length) { result[j] = a1[i1++]; } else if (i1 >= a1.length) { result[j] = a2[i2++]; } else if (a1[i1].compareTo(a2[i2]) <= 0) { result[j] = a1[i1++]; } else { result[j] = a2[i2++]; } } return result; } /* static inner class to contain code to run in thread */ private static class CodeForThread implements Runnable { private Integer[] data; private int firstIndex; private int lastIndex; int numThreads; private Integer[] result; public CodeForThread(Integer[] d, int first, int last, int nThreads) { data = d; firstIndex = first; lastIndex = last; numThreads = nThreads; } public void run() { result = mergesort(data, firstIndex, lastIndex, numThreads); } public Integer[] getResult() { return result; } } }