arrays - Java sum two double[][] with parallel stream -
let's have 2 matrices:
double[][] = new double[2][2] a[0][0] = 1 a[0][1] = 2 a[1][0] = 3 a[1][1] = 4 double[][] b = new double[2][2] b[0][0] = 1 b[0][1] = 2 b[1][0] = 3 b[1][1] = 4
in traditional way, sum matrices nested loop:
int rows = a.length; int cols = a[0].length; double[][] res = new double[rows][cols]; for(int = 0; < rows; i++){ for(int j = 0; j < cols; j++){ res[i][j] = a[i][j] + b[i][j]; } }
i'm new stream api think great fit use parallelstream
question if there's way , take advantage of parallel processing?
edit: not sure if right place here go: using suggestions putted stream test. set this: classical approach:
public class classicmatrix { private final double[][] components; private final int cols; private final int rows; public classicmatrix(final double[][] components){ this.components = components; this.rows = components.length; this.cols = components[0].length; } public classicmatrix addcomponents(final classicmatrix a) { final double[][] res = new double[rows][cols]; (int = 0; < rows; i++) { (int j = 0; j < rows; j++) { res[i][j] = components[i][j] + a.components[i][j]; } } return new classicmatrix(res); } }
using @dkatzel suggestion:
public class matrixstream1 { private final double[][] components; private final int cols; private final int rows; public matrixstream1(final double[][] components){ this.components = components; this.rows = components.length; this.cols = components[0].length; } public matrixstream1 addcomponents(final matrixstream1 a) { final double[][] res = new double[rows][cols]; intstream.range(0, rows*cols).parallel().foreach(i -> { int x = i/rows; int y = i%rows; res[x][y] = components[x][y] + a.components[x][y]; }); return new matrixstream1(res); } }
using @eugene suggestion:
public class matrixstream2 { private final double[][] components; private final int cols; private final int rows; public matrixstream2(final double[][] components) { this.components = components; this.rows = components.length; this.cols = components[0].length; } public matrixstream2 addcomponents(final matrixstream2 a) { final double[][] res = new double[rows][cols]; intstream.range(0, rows) .foreach(i -> arrays.parallelsetall(res[i], j -> components[i][j] * a.components[i][j])); return new matrixstream2(res); } }
and test class, running 3 independent times 1 each method (just replacing method name in main()):
public class matrixtest { private final static string path = "/media/manuel/workspace/data/"; public static void main(string[] args) { final list<double[]> lst = new arraylist<>(); (int = 100; < 8000; = + 400) { final double[] d = testclassic(i); system.out.println(d[0] + " : " + d[1]); lst.add(d); } ioutils.savetofile(path + "classic.csv", lst); } public static double[] testclassic(final int i) { final classicmatrix = new classicmatrix(rand(i)); final classicmatrix b = new classicmatrix(rand(i)); final long start = system.currenttimemillis(); final classicmatrix mul = a.addcomponents(b); final long = system.currenttimemillis(); final double elapsed = (now - start); return new double[] { (double) i, elapsed }; } public static double[] teststream1(final int i) { final matrixstream1 = new matrixstream1(rand(i)); final matrixstream1 b = new matrixstream1(rand(i)); final long start = system.currenttimemillis(); final matrixstream1 mul = a.addcomponents(b); final long = system.currenttimemillis(); final double elapsed = (now - start); return new double[] { (double) i, elapsed }; } public static double[] teststream2(final int i) { final matrixstream2 = new matrixstream2(rand(i)); final matrixstream2 b = new matrixstream2(rand(i)); final long start = system.currenttimemillis(); final matrixstream2 mul = a.addcomponents(b); final long = system.currenttimemillis(); final double elapsed = (now - start); return new double[] { (double) i, elapsed }; } private static double[][] rand(final int size) { final double[][] rnd = new double[size][size]; (int = 0; < size; i++) { (int j = 0; j < size; j++) { rnd[i][j] = math.random(); } } return rnd; } }
the results:
classic matrix size, time (ms) 100.0,1.0 500.0,5.0 900.0,5.0 1300.0,43.0 1700.0,94.0 2100.0,26.0 2500.0,33.0 2900.0,46.0 3300.0,265.0 3700.0,71.0 4100.0,87.0 4500.0,380.0 4900.0,432.0 5300.0,215.0 5700.0,238.0 6100.0,577.0 6500.0,677.0 6900.0,609.0 7300.0,584.0 7700.0,592.0 stream1, time(ms) 100.0,86.0 500.0,13.0 900.0,9.0 1300.0,47.0 1700.0,92.0 2100.0,29.0 2500.0,33.0 2900.0,46.0 3300.0,253.0 3700.0,71.0 4100.0,90.0 4500.0,352.0 4900.0,373.0 5300.0,497.0 5700.0,485.0 6100.0,579.0 6500.0,711.0 6900.0,800.0 7300.0,780.0 7700.0,902.0 stream2, time(ms) 100.0,111.0 500.0,42.0 900.0,12.0 1300.0,54.0 1700.0,97.0 2100.0,110.0 2500.0,177.0 2900.0,71.0 3300.0,250.0 3700.0,106.0 4100.0,359.0 4500.0,143.0 4900.0,233.0 5300.0,261.0 5700.0,289.0 6100.0,406.0 6500.0,814.0 6900.0,830.0 7300.0,828.0 7700.0,911.0
i made plot better comparison:
there's no improvement @ all. where's flaw? matrices small (7700 x 7700)? greater blows computer memory.
one way using arrays.parallelsetall
:
int rows = a.length; int cols = a[0].length; double[][] res = new double[rows][cols]; arrays.parallelsetall(res, -> { arrays.parallelsetall(res[i], j -> a[i][j] + b[i][j]); return res[i]; });
i'm not 100% sure, think inner call arrays.parallelsetall
might not worth overhead of generating inner parallelization each row's columns. maybe it's enough parallelize sum each row only:
arrays.parallelsetall(res, -> { arrays.setall(res[i], j -> a[i][j] + b[i][j]); return res[i]; });
anyway, should measure before adding parallelization algorithm, because many times overhead big it's not worth using it.
Comments
Post a Comment