I created a module that performs matrix multiplication using threads. It can be found here:
https://github.com/firefly-math/firefly-math-linear-real/
I tried to write a test to compare the implementation of a thread loop with the corresponding loop implementation in Apache Commons Math.
The control module is here:
https://github.com/firefly-math/firefly-math-benchmark
And the real indicator here:
https://github.com/firefly-math/firefly-math-benchmark/blob/master/src/main/java/com/fireflysemantics/benchmark/MultiplyBenchmark.java
When I run the test on matrices 100X100 and 1000X1000, it turns out that the Apache Commons Math (uses the for loop) is 10 times faster (approximately) than the corresponding stream implementation.
Benchmark Mode Cnt Score Error Units
MultiplyBenchmark.multiplyCM1000_1000 avgt 30 1040.804 ± 11.796 ms/op
MultiplyBenchmark.multiplyCM100_100 avgt 30 0.790 ± 0.010 ms/op
MultiplyBenchmark.multiplyFM1000_1000 avgt 30 11981.228 ± 405.812 ms/op
MultiplyBenchmark.multiplyFM100_100 avgt 30 7.224 ± 0.685 ms/op
I did something wrong in the benchmark (I hope :))?
I add proven methods so that everyone can see what is being compared. This is the Apache Commons Math Array2DRowRealMatrix.multiply () method:
public Array2DRowRealMatrix multiply(final Array2DRowRealMatrix m)
throws DimensionMismatchException {
MatrixUtils.checkMultiplicationCompatible(this, m);
final int nRows = this.getRowDimension();
final int nCols = m.getColumnDimension();
final int nSum = this.getColumnDimension();
final double[][] outData = new double[nRows][nCols];
final double[] mCol = new double[nSum];
final double[][] mData = m.data;
for (int col = 0; col < nCols; col++) {
for (int mRow = 0; mRow < nSum; mRow++) {
mCol[mRow] = mData[mRow][col];
}
for (int row = 0; row < nRows; row++) {
final double[] dataRow = data[row];
double sum = 0;
for (int i = 0; i < nSum; i++) {
sum += dataRow[i] * mCol[i];
}
outData[row][col] = sum;
}
}
return new Array2DRowRealMatrix(outData, false);
}
And this is the corresponding stream implementation:
public static BinaryOperator<SimpleMatrix> multiply(boolean parallel) {
return (m1, m2) -> {
checkMultiplicationCompatible(m1, m2);
double[][] a1 = m1.toArray();
double[][] a2 = m2.toArray();
Stream<double[]> stream = Arrays.stream(a1);
stream = parallel ? stream.parallel() : stream;
final double[][] result =
stream.map(r -> range(0, a2[0].length)
.mapToDouble(i -> range(0, a2.length).mapToDouble(j -> r[j]
* a2[j][i]).sum())
.toArray()).toArray(double[][]::new);
return new SimpleMatrix(result);
};
}
TIA, Ole
source
share