// Fri 11-15 update: // - command-line arguments for dataSize and nWorkers // - getSum(double[]) method for result verification // - no printing from run() import java.util.Arrays; public class SumThread extends Thread { private static double[] shared; private int id; private int startIndex, endIndex; private double sum; public SumThread(double[] data, int id, int i, int j) { this.id = id; startIndex = i; endIndex = j; shared = data; } public double getResult() { return sum; } public String toString() { return String.format("%02d: result=%.2f startIndex=%d", id, sum, startIndex); } public void run() { sum = 0; for (int i = startIndex; i <= endIndex; ++i) { sum += shared[i]; } // note: IO is one of the bottlenecks in computing // accessing storage (hard drive, usb stick, ...) //System.out.println(toString()); //System.out.printf("id: %d, i=%d, j=%d, sum=%f\n", id, startIndex, endIndex, sum); } public static double[] generateData(int n, double min, double max) { double[] data = new double[n]; double range = max - min + 1; //for (double d : data) { // Exercise: why wouldn't this work? // d = Math.random() * range + min; // } // Math.random() ==> [0, 1) ==> [min, max] for (int i = 0; i < n; ++i) { data[i] = (int) (Math.random() * range + min); // store range + min?? NO, why? } return data; } public static double getSum(double[] array) { double sum = 0; for (double num : array) { sum += num; } return sum; } // args: command line arguments (@ terminal prompt) // usage: java SumThread [dataSize nWorkers] public static void main(String[] args) { System.out.println("command line arguments: " + Arrays.toString(args)); // default setting int dataSize = 10; int nWorkers = 2; // dataSize is given if (args.length > 0) { dataSize = Integer.parseInt(args[0]); // "123" ==> 123 } // dataSize AND nWorkers are given if (args.length > 1) { nWorkers = Integer.parseInt(args[1]); // work cannot be evenly distributed if (dataSize % nWorkers != 0) { nWorkers = 1; } } double[] data = generateData(dataSize, 1, 9); // timing the performance long startTime = System.nanoTime(); // assumption: dataSize is divisible by nWorkers // divide work equally among threads int workSize = dataSize / nWorkers; SumThread[] workers = new SumThread[nWorkers]; // // startIndex = i * workSize; // endIndex = (i + 1) * workSize - 1; // startIndex + workSize - 1 // start/end-index for thread 0 int startIndex = 0; int endIndex = workSize - 1; for (int i = 0; i < nWorkers; ++i) { workers[i] = new SumThread(data, i, startIndex, endIndex); startIndex += workSize; endIndex += workSize; } // start threads for (Thread st : workers) { st.start(); } // wait until ALL threads are done try { for (SumThread st : workers) { st.join(); } } catch(InterruptedException e) { System.err.println("Workers were unable to complete their work due to interruptions"); e.printStackTrace(); } // collect the result double sum = 0.0; for (SumThread st : workers) { // cannot use Thread type because getResult() is not defined in Thread sum += st.getResult(); } long endTime = System.nanoTime(); double duration = (endTime - startTime) / 1000000.0; // publish the result System.out.printf("dataSize: %d, nWorkers: %d, result: %.2f, time (msec): %.2f\n", dataSize, nWorkers, sum, duration); System.out.printf("verify result: %.2f\n", getSum(data)); //System.out.printf("verification data: %s\n", Arrays.toString(data)); } }