package edu.rice.hj.example.comp322.labs.lab2; 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.*; /** * ArraySum1.hj --- Parallel iterative example program for computing the sum of an array *

* This example program creates an array of n random int's, and computes their sum in parallel. The default value of n * is 8, but any array size can be provided as argv[0] by going into the run configuration and putting it in the program * arguments field on intelliJ, or by typing java ArraySum1 n on the command line *

* To obtain abstract performance metrics, select the appropriate compiler option. *

* NOTE: this example program is for illustrative purposes, and is not intended to be used as a performance benchmark. * * @author Vivek Sarkar (vsarkar@rice.edu) */ public class ArraySum1 { static final int default_n = 8; static final String err = "Incorrect argument for array size (should be > 0), assuming n = " + default_n; /** * Main method, runs the ArraySum * * @param argv - the input parameters */ public static void main(String[] argv) { // Setup metrics HjSystemProperty.abstractMetrics.set(true); launchHabaneroApp(() -> { final int n = readLengthArgument(argv); // Initialization final int[] X = new int[n]; final Random myRand = new Random(n); for (int i = 0; i < n; i++) { X[i] = myRand.nextInt(n); } // Parallel reduction for (int step = 1; step < n; step *= 2) { int size = ceilDiv(n, 2 * step); final int sstep = step; finish(() -> { for (int i = 0; i < size; i++) { final int ii = i; asyncNb(() -> { // if condition ensures that algorithm works correctly when X.length is not a power of 2 final int rightIndex = (2 * ii + 1) * sstep; final int leftIndex = 2 * ii * sstep; if (rightIndex < X.length) { // local variables X, step, size are copied on entry to the async, analogous to method call parameters X[leftIndex] = doOperation(X, leftIndex, rightIndex); } }); } }); // finish-for-async } // Output System.out.println("Sum of " + n + " elements = " + X[0] + " (should be 27 for n = 8)"); }, () -> { // Print out the metrics data final HjMetrics actualMetrics = abstractMetrics(); AbstractMetricsManager.dumpStatistics(actualMetrics); }); } /** * Reads the input paramter to the program. If there is no input parameter or the input is illegal, uses a default * n * * @param argv - the string array of input parameters * @return the number of random ints to use */ protected static int readLengthArgument(final String[] argv) { int n; 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; } return n; } /** * Divide x by y, and round up to next largest int * * @param x - dividend * @param y - divisor * @return quotient rounded to the up to an integer */ protected static int ceilDiv(int x, int y) { return (x + y - 1) / y; } /** * adds two elements in an array, and increments the work counter by 1 * * @param x - the arry * @param leftIndex - the first index to add * @param rightIndex - the second index to add * @return - the sum of the values at the two indexes */ protected static int doOperation(final int[] x, final int leftIndex, final int rightIndex) { // count each + operator as 1 unit of work in the abstract performance metrics doWork(1); return x[leftIndex] + x[rightIndex]; } }