import edu.rice.hj.api.HjPhaser; import edu.rice.hj.api.HjPhaserMode; import edu.rice.hj.api.HjRegion.HjRegion1D; import static edu.rice.hj.Module1.*; /** *

OneDimAveragingSol class.

* * @author Shams Imam (shams@rice.edu) */ public class OneDimAveraging { /** * Constant initialOutput */ public static double[] initialOutput; /** *

main.

* * @param args an array of {@link String} objects. */ public static void main(final String[] args) { final int tasks = (args.length > 0) ? Integer.parseInt(args[0]) : 8; final int n = (args.length > 1) ? Integer.parseInt(args[1]) : 200_000; final int iterations = (args.length > 2) ? Integer.parseInt(args[2]) : 20_000; final int rounds = (args.length > 3) ? Integer.parseInt(args[3]) : 5; printParams(tasks, n, iterations, rounds); { // initial run to set the output to be equal to the sequential run final OneDimAveraging initialObj = new OneDimAveraging(n); initialObj.runSequential(iterations); setOutput(initialObj); } System.out.println("Timed executions:"); finish(() -> { for (int r = 0; r < rounds; r++) { System.out.println(" Round: " + r + (r == 0 ? " [ignore: warm up for JIT]" : "")); finish(() -> { final OneDimAveragingSol barrierBody = new OneDimAveragingSol(n); timeIt(String.format("Barrier [tasks=%d]", tasks), () -> { barrierBody.runBarrier(iterations, tasks); }, barrierBody::validateOutput); }); finish(() -> { final OneDimAveragingSol peer2PeerBody = new OneDimAveragingSol(n); timeIt(String.format("Peer-To-Peer [tasks=%d]", tasks), () -> { peer2PeerBody.runPeerToPeer(iterations, tasks); }, peer2PeerBody::validateOutput); }); System.out.println(); } }); } /** *

setOutput.

* * @param oneDimAveraging a {@link edu.rice.hj.example.comp322.labs.lab6.OneDimAveraging} object. */ public static void setOutput(final OneDimAveraging oneDimAveraging) { if (OneDimAveraging.initialOutput != null) { System.out.println("Warning: initialOutput has already been set."); } OneDimAveraging.initialOutput = oneDimAveraging.myVal; } /** *

printParams.

* * @param tasks a int. * @param n a int. * @param iterations a int. * @param rounds a int. */ public static void printParams(final int tasks, final int n, final int iterations, final int rounds) { System.out.println("Configuration: "); System.out.println(" # tasks for parallel run: " + tasks); System.out.println(" Array size n: " + n); System.out.println(" # iterations: " + iterations); System.out.println(" Rounds: " + rounds + " (to reduce JIT overhead)"); System.out.println(); } private static void timeIt( final String label, final Runnable actualBody, final Runnable postExecBody) { final long s = System.currentTimeMillis(); actualBody.run(); final long e = System.currentTimeMillis(); postExecBody.run(); System.out.printf("%35s Time: %6d ms. \n", label, (e - s)); } public double[] myNew, myVal; public int n; /** *

Constructor for OneDimAveragingSol.

* * @param n a int. */ public OneDimAveraging(final int n) { this.n = n; this.myNew = new double[n + 2]; this.myVal = new double[n + 2]; this.myVal[n + 1] = 1.0; } /** *

validateOutput.

*/ public void validateOutput() { if (OneDimAveraging.initialOutput == null) { System.out.println("initialOutput is null"); return; } else if (myVal == null) { System.out.println("myVal is null"); return; } for (int i = 0; i < n + 2; i++) { final double init = OneDimAveraging.initialOutput[i]; final double curr = myVal[i]; final double diff = Math.abs(init - curr); if (diff > 1e-20) { System.out.println("ERROR: validation failed!"); System.out.println(" Diff: myVal[" + i + "]=" + curr + " != initialOutput[" + i + "]=" + init); break; } } } private static int ceilDiv(final int n, final int d) { final int m = n / d; if (m * d == n) { return m; } else { return (m + 1); } } /** *

runSequential.

* * @param iterations a int. */ public void runSequential(final int iterations) { for (int iter = 0; iter < iterations; iter++) { for (int j = 1; j <= n; j++) { myNew[j] = (myVal[j - 1] + myVal[j + 1]) / 2.0; } final double[] temp = myNew; myNew = myVal; myVal = temp; } } /** *

runBarrier.

* * @param iterations a int. * @param tasks a int. */ public void runBarrier(final int iterations, final int tasks) { final HjRegion1D iterSpace = newRectangularRegion1D(1, n); finish(() -> { final HjPhaser ph = newPhaser(HjPhaserMode.SIG_WAIT); forseq(0, tasks - 1, (Integer i) -> { asyncPhased(ph.inMode(HjPhaserMode.SIG_WAIT), () -> { final HjRegion1D myGroup = myGroup(i, iterSpace, tasks); double[] lMyVal = myVal; double[] lMyNew = myNew; for (int iter = 0; iter < iterations; iter++) { final double[] constMyVal = lMyVal; final double[] constMyNew = lMyNew; forseq(myGroup, (j) -> { constMyNew[j] = (constMyVal[j - 1] + constMyVal[j + 1]) / 2.0; }); double[] temp = lMyNew; lMyNew = lMyVal; lMyVal = temp; next(); } }); }); }); } /** *

runPeerToPeer.

* * @param iterations a int. * @param tasks a int. */ public void runPeerToPeer(final int iterations, final int tasks) { // TODO Convert the Barrier version to Phaser version final HjRegion1D iterSpace = newRectangularRegion1D(1, n); finish(() -> { final HjPhaser ph = newPhaser(HjPhaserMode.SIG_WAIT); forseq(0, tasks - 1, (Integer i) -> { asyncPhased(ph.inMode(HjPhaserMode.SIG_WAIT), () -> { final HjRegion1D myGroup = myGroup(i, iterSpace, tasks); double[] lMyVal = myVal; double[] lMyNew = myNew; for (int iter = 0; iter < iterations; iter++) { final double[] constMyVal = lMyVal; final double[] constMyNew = lMyNew; forseq(myGroup, (j) -> { constMyNew[j] = (constMyVal[j - 1] + constMyVal[j + 1]) / 2.0; }); double[] temp = lMyNew; lMyNew = lMyVal; lMyVal = temp; next(); } }); }); }); } }