From 90c10083e92ad0c27fb3451c37ddbceac4b1298a Mon Sep 17 00:00:00 2001 From: Alberto Venturini Date: Sun, 10 Sep 2017 21:18:49 +0200 Subject: [PATCH] Added fork-join version of JuliaSetCalculator --- src/ExecutorServiceJuliaSetCalculator.java | 81 +++++++++++++++++++++ src/ForkJoinJuliaSetCalculator.java | 76 ++++++++++++++++++++ src/JuliaSetCalculator.java | 82 +++------------------- src/MainClass.java | 2 +- 4 files changed, 166 insertions(+), 75 deletions(-) create mode 100644 src/ExecutorServiceJuliaSetCalculator.java create mode 100644 src/ForkJoinJuliaSetCalculator.java diff --git a/src/ExecutorServiceJuliaSetCalculator.java b/src/ExecutorServiceJuliaSetCalculator.java new file mode 100644 index 0000000..ff6721f --- /dev/null +++ b/src/ExecutorServiceJuliaSetCalculator.java @@ -0,0 +1,81 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + + +public class ExecutorServiceJuliaSetCalculator implements JuliaSetCalculator { + private int width; + private int height; + private int[][] iterations; + + public ExecutorServiceJuliaSetCalculator(final int width, final int height) { + this.width = width; + this.height = height; + iterations = new int[width][height]; + } + + public int[][] calculate( + final int maxIterations, + final double zoom, + final double cx, + final double cy, + final double moveX, + final double moveY) { + + /** + * Each task calculates one row. I.e. if we have 'width*height' iterations, + * we have 'width' tasks, each of which calculates the value of 'row' iterations. + */ + class JuliaTask implements Runnable { + + private int x; + + JuliaTask(int x) { + this.x = x; + } + + @Override + public void run() { + double zx, zy; + for(int y = 0; y < height; y++) { + zx = 1.5 * (x - width / 2) / (0.5 * zoom * width) + moveX; + zy = (y - height / 2) / (0.5 * zoom * height) + moveY; + int i = maxIterations; + while (zx * zx + zy * zy < 4 && i > 0) { + double tmp = zx * zx - zy * zy + cx; + zy = 2.0 * zx * zy + cy; + zx = tmp; + i--; + } + iterations[x][y] = i; + } + } + } + + long startTime = System.currentTimeMillis(); + + ExecutorService executorService = Executors.newWorkStealingPool(8); + for(int x = 0; x < width; x++) { + JuliaTask task = new JuliaTask(x); + executorService.submit(task); + } + + executorService.shutdown(); + + try { + executorService.awaitTermination(5, TimeUnit.SECONDS); + } catch (Exception ex) { + System.out.println(ex); + } + + + long endTime = System.currentTimeMillis(); + + System.out.println(endTime - startTime); + + return iterations; + } + + + +} diff --git a/src/ForkJoinJuliaSetCalculator.java b/src/ForkJoinJuliaSetCalculator.java new file mode 100644 index 0000000..8e90b01 --- /dev/null +++ b/src/ForkJoinJuliaSetCalculator.java @@ -0,0 +1,76 @@ +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveAction; + +public class ForkJoinJuliaSetCalculator implements JuliaSetCalculator { + + private int width; + private int height; + private int[][] iterations; + + public ForkJoinJuliaSetCalculator(final int width, final int height) { + this.width = width; + this.height = height; + iterations = new int[width][height]; + } + + @Override + public int[][] calculate(int maxIterations, double zoom, double cx, double cy, double moveX, double moveY) { + + class JuliaTask extends RecursiveAction { + + private int startInclusive; + private int endExclusive; + + private final int THRESHOLD = 10; + + JuliaTask(int startInclusive, int endExclusive) { + this.startInclusive = startInclusive; + this.endExclusive = endExclusive; + } + + private void computeDirectly() { + double zx, zy; + + for(int x = startInclusive; x < endExclusive; x++) { + for (int y = 0; y < height; y++) { + zx = 1.5 * (x - width / 2) / (0.5 * zoom * width) + moveX; + zy = (y - height / 2) / (0.5 * zoom * height) + moveY; + int i = maxIterations; + while (zx * zx + zy * zy < 4 && i > 0) { + double tmp = zx * zx - zy * zy + cx; + zy = 2.0 * zx * zy + cy; + zx = tmp; + i--; + } + iterations[x][y] = i; + } + } + } + + @Override + protected void compute() { + if(endExclusive - startInclusive < THRESHOLD) { + computeDirectly(); + } else { + int middle = (startInclusive + endExclusive) / 2; + JuliaTask task1 = new JuliaTask(startInclusive, middle); + JuliaTask task2 = new JuliaTask(middle, endExclusive); + invokeAll(task1, task2); + } + } + } + + long startTime = System.currentTimeMillis(); + + JuliaTask task = new JuliaTask(0, width); + System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", Integer.toString(8)); + ForkJoinPool.commonPool().invoke(task); + + long endTime = System.currentTimeMillis(); + System.out.println(endTime - startTime); + + return iterations; + + } + +} diff --git a/src/JuliaSetCalculator.java b/src/JuliaSetCalculator.java index 9910788..db7fcb3 100644 --- a/src/JuliaSetCalculator.java +++ b/src/JuliaSetCalculator.java @@ -1,77 +1,11 @@ -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - - -public class JuliaSetCalculator { - private int width; - private int height; - private int[][] iterations; - - public JuliaSetCalculator(final int width, final int height) { - this.width = width; - this.height = height; - iterations = new int[width][height]; - } - - public int[][] calculate( - final int maxIterations, - final double zoom, - final double cx, - final double cy, - final double moveX, - final double moveY) { - - class JuliaTask implements Runnable { - - private int x; - - JuliaTask(int x) { - this.x = x; - } - - @Override - public void run() { - double zx, zy; - for(int y = 0; y < height; y++) { - zx = 1.5 * (x - width / 2) / (0.5 * zoom * width) + moveX; - zy = (y - height / 2) / (0.5 * zoom * height) + moveY; - int i = maxIterations; - while (zx * zx + zy * zy < 4 && i > 0) { - double tmp = zx * zx - zy * zy + cx; - zy = 2.0 * zx * zy + cy; - zx = tmp; - i--; - } - iterations[x][y] = i; - } - } - } - - long startTime = System.currentTimeMillis(); - - ExecutorService executorService = Executors.newWorkStealingPool(8); - for(int x = 0; x < width; x++) { - JuliaTask task = new JuliaTask(x); - executorService.submit(task); - } - - executorService.shutdown(); - - try { - executorService.awaitTermination(5, TimeUnit.SECONDS); - } catch (Exception ex) { - System.out.println(ex); - } - - - long endTime = System.currentTimeMillis(); - - System.out.println(endTime - startTime); - - return iterations; - } - +public interface JuliaSetCalculator { + int[][] calculate( + int maxIterations, + double zoom, + double cx, + double cy, + double moveX, + double moveY); } diff --git a/src/MainClass.java b/src/MainClass.java index 97d3e88..17f3a92 100644 --- a/src/MainClass.java +++ b/src/MainClass.java @@ -7,7 +7,7 @@ public class MainClass { int width = 1200; int height = 800; - JuliaSetCalculator juliaSetCalculator = new JuliaSetCalculator(width, height); + JuliaSetCalculator juliaSetCalculator = new ForkJoinJuliaSetCalculator(width, height); JuliaSetPanel juliaSetPanel = new JuliaSetPanel(juliaSetCalculator, width, height); SwingUtilities.invokeLater(() -> {