| /* | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* | |
| * This file is available under and governed by the GNU General Public | |
| * License version 2 only, as published by the Free Software Foundation. | |
| * However, the following notice accompanied the original version of this | |
| * file: | |
| * | |
| * Written by Doug Lea with assistance from members of JCP JSR-166 | |
| * Expert Group and released to the public domain, as explained at | |
| * http://creativecommons.org/publicdomain/zero/1.0/ | |
| */ | |
| /* | |
| * @test | |
| * @bug 6865571 | |
| * @summary Numerical Integration using fork/join | |
| * @run main Integrate reps=1 forkPolicy=dynamic | |
| * @run main Integrate reps=1 forkPolicy=serial | |
| * @run main Integrate reps=1 forkPolicy=fork | |
| */ | |
| import java.util.concurrent.ForkJoinPool; | |
| import java.util.concurrent.RecursiveAction; | |
| /** | |
| * Sample program using Gaussian Quadrature for numerical integration. | |
| * This version uses a simplified hardwired function. Inspired by a | |
| * <A href="http://www.cs.uga.edu/~dkl/filaments/dist.html"> | |
| * Filaments</A> demo program. | |
| */ | |
| public final class Integrate { | |
| static final double errorTolerance = 1.0e-11; | |
| /** for time conversion */ | |
| static final long NPS = (1000L * 1000 * 1000); | |
| static final int SERIAL = -1; | |
| static final int DYNAMIC = 0; | |
| static final int FORK = 1; | |
| /** the function to integrate */ | |
| static double computeFunction(double x) { | |
| return (x * x + 1.0) * x; | |
| } | |
| static final double start = 0.0; | |
| static final double end = 1536.0; | |
| /** | |
| * The number of recursive calls for | |
| * integrate from start to end. | |
| * (Empirically determined) | |
| */ | |
| static final int calls = 263479047; | |
| static String keywordValue(String[] args, String keyword) { | |
| for (String arg : args) | |
| if (arg.startsWith(keyword)) | |
| return arg.substring(keyword.length() + 1); | |
| return null; | |
| } | |
| static int intArg(String[] args, String keyword, int defaultValue) { | |
| String val = keywordValue(args, keyword); | |
| return (val == null) ? defaultValue : Integer.parseInt(val); | |
| } | |
| static int policyArg(String[] args, String keyword, int defaultPolicy) { | |
| String val = keywordValue(args, keyword); | |
| if (val == null) return defaultPolicy; | |
| if (val.equals("dynamic")) return DYNAMIC; | |
| if (val.equals("serial")) return SERIAL; | |
| if (val.equals("fork")) return FORK; | |
| throw new Error(); | |
| } | |
| /** | |
| * Usage: Integrate [procs=N] [reps=N] forkPolicy=serial|dynamic|fork | |
| */ | |
| public static void main(String[] args) throws Exception { | |
| final int procs = intArg(args, "procs", | |
| Runtime.getRuntime().availableProcessors()); | |
| final int forkPolicy = policyArg(args, "forkPolicy", DYNAMIC); | |
| ForkJoinPool g = new ForkJoinPool(procs); | |
| System.out.println("Integrating from " + start + " to " + end + | |
| " forkPolicy = " + forkPolicy); | |
| long lastTime = System.nanoTime(); | |
| for (int reps = intArg(args, "reps", 10); reps > 0; reps--) { | |
| double a; | |
| if (forkPolicy == SERIAL) | |
| a = SQuad.computeArea(g, start, end); | |
| else if (forkPolicy == FORK) | |
| a = FQuad.computeArea(g, start, end); | |
| else | |
| a = DQuad.computeArea(g, start, end); | |
| long now = System.nanoTime(); | |
| double s = (double) (now - lastTime) / NPS; | |
| lastTime = now; | |
| System.out.printf("Calls/sec: %12d", (long) (calls / s)); | |
| System.out.printf(" Time: %7.3f", s); | |
| System.out.printf(" Area: %12.1f", a); | |
| System.out.println(); | |
| } | |
| System.out.println(g); | |
| g.shutdown(); | |
| } | |
| // Sequential version | |
| static final class SQuad extends RecursiveAction { | |
| static double computeArea(ForkJoinPool pool, double l, double r) { | |
| SQuad q = new SQuad(l, r, 0); | |
| pool.invoke(q); | |
| return q.area; | |
| } | |
| final double left; // lower bound | |
| final double right; // upper bound | |
| double area; | |
| SQuad(double l, double r, double a) { | |
| this.left = l; this.right = r; this.area = a; | |
| } | |
| public final void compute() { | |
| double l = left; | |
| double r = right; | |
| area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area); | |
| } | |
| static final double recEval(double l, double r, double fl, | |
| double fr, double a) { | |
| double h = (r - l) * 0.5; | |
| double c = l + h; | |
| double fc = (c * c + 1.0) * c; | |
| double hh = h * 0.5; | |
| double al = (fl + fc) * hh; | |
| double ar = (fr + fc) * hh; | |
| double alr = al + ar; | |
| if (Math.abs(alr - a) <= errorTolerance) | |
| return alr; | |
| else | |
| return recEval(c, r, fc, fr, ar) + recEval(l, c, fl, fc, al); | |
| } | |
| } | |
| //.................................... | |
| // ForkJoin version | |
| static final class FQuad extends RecursiveAction { | |
| static double computeArea(ForkJoinPool pool, double l, double r) { | |
| FQuad q = new FQuad(l, r, 0); | |
| pool.invoke(q); | |
| return q.area; | |
| } | |
| final double left; // lower bound | |
| final double right; // upper bound | |
| double area; | |
| FQuad(double l, double r, double a) { | |
| this.left = l; this.right = r; this.area = a; | |
| } | |
| public final void compute() { | |
| double l = left; | |
| double r = right; | |
| area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area); | |
| } | |
| static final double recEval(double l, double r, double fl, | |
| double fr, double a) { | |
| double h = (r - l) * 0.5; | |
| double c = l + h; | |
| double fc = (c * c + 1.0) * c; | |
| double hh = h * 0.5; | |
| double al = (fl + fc) * hh; | |
| double ar = (fr + fc) * hh; | |
| double alr = al + ar; | |
| if (Math.abs(alr - a) <= errorTolerance) | |
| return alr; | |
| FQuad q = new FQuad(l, c, al); | |
| q.fork(); | |
| ar = recEval(c, r, fc, fr, ar); | |
| if (!q.tryUnfork()) { | |
| q.quietlyJoin(); | |
| return ar + q.area; | |
| } | |
| return ar + recEval(l, c, fl, fc, al); | |
| } | |
| } | |
| // ........................... | |
| // Version using on-demand Fork | |
| static final class DQuad extends RecursiveAction { | |
| static double computeArea(ForkJoinPool pool, double l, double r) { | |
| DQuad q = new DQuad(l, r, 0); | |
| pool.invoke(q); | |
| return q.area; | |
| } | |
| final double left; // lower bound | |
| final double right; // upper bound | |
| double area; | |
| DQuad(double l, double r, double a) { | |
| this.left = l; this.right = r; this.area = a; | |
| } | |
| public final void compute() { | |
| double l = left; | |
| double r = right; | |
| area = recEval(l, r, (l * l + 1.0) * l, (r * r + 1.0) * r, area); | |
| } | |
| static final double recEval(double l, double r, double fl, | |
| double fr, double a) { | |
| double h = (r - l) * 0.5; | |
| double c = l + h; | |
| double fc = (c * c + 1.0) * c; | |
| double hh = h * 0.5; | |
| double al = (fl + fc) * hh; | |
| double ar = (fr + fc) * hh; | |
| double alr = al + ar; | |
| if (Math.abs(alr - a) <= errorTolerance) | |
| return alr; | |
| DQuad q = null; | |
| if (getSurplusQueuedTaskCount() <= 3) | |
| (q = new DQuad(l, c, al)).fork(); | |
| ar = recEval(c, r, fc, fr, ar); | |
| if (q != null && !q.tryUnfork()) { | |
| q.quietlyJoin(); | |
| return ar + q.area; | |
| } | |
| return ar + recEval(l, c, fl, fc, al); | |
| } | |
| } | |
| } |