/* * Java program to test/time quicksort. * * parallel version, naive approach: * * on split, creates an independent thread for one of the subproblems if * that would not cause there to be more than designated number of threads. * * command-line arguments: number of elements to sort, seed for RNG, number * of threads. */ package csci3366.hw4; import java.util.Random; public class QuickSortPar1 { /* main method */ public static void main(String[] args) { String usageMsg = "arguments are numElements seed numThreads"; /* process command-line arguments */ if (args.length < 3) { System.err.println(usageMsg); System.exit(1); } int n = 0; int seed = 0; int numThreads = 0; try { n = Integer.parseInt(args[0]); seed = Integer.parseInt(args[1]); numThreads = Integer.parseInt(args[2]); } catch (NumberFormatException e) { System.err.println("arguments must be integers"); System.exit(1); } /* 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(); sort(ints, numThreads); long endTime = System.currentTimeMillis(); /* check whether sort succeeded */ if (isSorted(ints)) { System.out.println("sort succeeded"); } else { System.out.println("sort failed"); } /* print timing result */ System.out.println("Parallel version, v1, with " + numThreads + " threads"); System.out.println("Time for sort of " + n + " random integers (seed " + seed + ") is " + ((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 quicksort routine */ public static void sort(Integer[] data, int numThreads) { sort(data, 0, data.length-1, numThreads); } /* * recursive quicksort: * sorts data[firstIndex..lastIndex] in place, * using numThreads threads */ private static void sort(Integer[] data, int startIndex, int endIndex, int numThreads) { if (startIndex < endIndex) { int splitIndex = partition(data, startIndex, endIndex); Thread otherThread = null; if (numThreads > 1) { /* start other thread to sort left half */ otherThread = new Thread(new CodeForThread(data, startIndex, splitIndex-1, numThreads/2)); otherThread.start(); /* FIXME? System.err.printf("new thread, left fraction %6.4f\n", ((double) (splitIndex - startIndex)) / ((double) (endIndex - startIndex + 1))); */ } else { sort(data, startIndex, splitIndex-1, numThreads/2); } sort(data, splitIndex+1, endIndex, 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"); } } } } /* * rearranges array elements from startIndex through endIndex such that * elements <= pivot are to the left of splitIndex and elements > pivot * are to the right of splitIndex, places pivot at splitIndex, and * returns splitIndex. */ private static int partition(Integer[] data, int startIndex, int endIndex) { int k = startIndex + 1; int m = startIndex + 1; /* * loop invariant: * data[startIndex .. k-1] <= data[startIndex] * data[k .. m-1] > data[startIndex] */ while (m <= endIndex) { if (data[m].compareTo(data[startIndex]) > 0) { } else { swap(data, k, m); ++k; } ++m; } swap(data, startIndex, k-1); return k-1; } /* swaps array elements */ private static void swap(Integer[] data, int i, int j) { Integer temp = data[i]; data[i] = data[j]; data[j] = temp; } /* 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; public CodeForThread(Integer[] d, int first, int last, int nThreads) { data = d; firstIndex = first; lastIndex = last; numThreads = nThreads; } public void run() { sort(data, firstIndex, lastIndex, numThreads); } } }