import edu.rice.hj.api.HjFuture; import edu.rice.hj.api.HjMetrics; import edu.rice.hj.runtime.config.HjSystemProperty; import edu.rice.hj.runtime.metrics.AbstractMetricsManager; import java.util.Random; import static edu.rice.hj.Module1.*; /** * ArraySum4.java --- Parallel recursive example program for computing the sum of an array using futures * with variable execution times for add operations. * * @author Vivek Sarkar (vsarkar@rice.edu) * * This example program creates an array of n random int's, and computes their sum in parallel. * The default value of n is 128, but any size can be provided as argv[0] * * NOTE: this example program is intended for illustrating abstract performance metrics, * and is not intended to be used as a benchmark for real performance. */ public class ArraySum4 { static final int default_n = 128; static final String err = "Incorrect argument for array size (should be > 0), assuming n = " + default_n; /** * Computes the sum of an array of integers between two indexes * @param X the array to sum up * @param lo The leftmost index to use in the sum * @param hi the rightmost index to use in the sum * @return - the sum of all elements in between the two indexes */ static int computeSum(int[] X, int lo, int hi) { if ( lo > hi ) { return 0; } else if ( lo == hi ) { return X[lo]; } else { int mid = (lo+hi)/2; final HjFuture sum1 = future(() -> computeSum(X, lo, mid)); final HjFuture sum2 = future(() -> computeSum(X, mid+1, hi)); int local_sum = sum1.get() + sum2.get(); // Variant of ArraySum1 -- count work as sum of the bits in input operands, // and assume that everything else is free doWork(countBits(sum1.get()) + countBits(sum2.get())); return local_sum; } } // computeSum /** * Main function. Input can take one parameter, which is size * of the array. If there are no input parameters, use a default size * @param argv - the input parameter */ public static void main(String[] argv) { // Setup metrics System.setProperty(HjSystemProperty.abstractMetrics.propertyKey(), "true"); initializeHabanero(); // Initialization int n; int[] X; if (argv.length != 0) { try { n = Integer.parseInt(argv[0]); if (n <= 0) { // Bad value of n System.out.println(err); n = default_n; } } catch (Throwable e) { System.out.println(err); n = default_n; } } else { // argv.length == 0 n = default_n; } X = new int[n]; Random myRand = new Random(n); for (int i = 0; i < n; i++) X[i] = myRand.nextInt(n); // Recursive parallel computation int sum = computeSum(X, 0, n-1); // Output System.out.println("Sum of " + n + " elements = " + sum); // Print out the metrics data finalizeHabanero(); final HjMetrics actualMetrics = abstractMetrics(); AbstractMetricsManager.dumpStatistics(actualMetrics); System.out.println(actualMetrics); } /* * Return the number of bits in x for use in abstract performance metrics. * If x is negative, return the number of bits in -x. * @param x an integer * @return the number of bits in the input */ static int countBits(int x) { // Convert x to a positive value if (x == Integer.MIN_VALUE) x = Integer.MAX_VALUE; else if (x < 0) x = -x; return 32 - Integer.numberOfLeadingZeros(x); } }