package edu.rice.hj.example.comp322.labs.lab3;
import edu.rice.hj.api.HjFuture;
import edu.rice.hj.api.HjMetrics;
import edu.rice.hj.api.SuspendableException;
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.hj --- Parallel recursive example program for computing the sum of an array using futures with variable
* execution times for add operations.
*
* This example program creates an array of n random int's, and computes their sum in parallel. The default value of n
* is 1024, but any size can be provided as argv[0] by using the command "run ArraySum2 size" in the DrHJ Interactions
* Pane or "hj ArraySum2 size" on the command line.
*
* NOTE: this example program is intended for illustrating abstract performance metrics, and is not intended to be used
* as a benchmark for real performance.
*
* @author Vivek Sarkar (vsarkar@rice.edu)
*/
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;
static int computeSum(final int[] X, final int lo, final int hi) throws SuspendableException {
if (lo > hi) {
return 0;
} else if (lo == hi) {
return X[lo];
} else {
final int mid = (lo + hi) / 2;
final HjFuture sum1 = future(() -> computeSum(X, lo, mid));
final HjFuture sum2 = future(() -> computeSum(X, mid + 1, hi));
final 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.
*
* @param argv an array of {@link String} objects.
*/
public static void main(final String[] argv) {
// Setup metrics
HjSystemProperty.abstractMetrics.set(true);
launchHabaneroApp(() -> {
// Initialization
int n;
final 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 (final Throwable e) {
System.out.println(err);
n = default_n;
}
} else { // argv.length == 0
n = default_n;
}
X = new int[n];
final Random myRand = new Random(n);
for (int i = 0; i < n; i++) {
X[i] = myRand.nextInt(n);
}
// Recursive parallel computation
final int sum = computeSum(X, 0, n - 1);
// Output
System.out.println("Sum of " + n + " elements = " + sum);
}, () -> {
// Print out the metrics data
final HjMetrics actualMetrics = abstractMetrics();
AbstractMetricsManager.dumpStatistics(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.
*/
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);
}
}