diff --git a/src/Benchmark/LinearAlgebra/DenseMatrixProduct.cs b/src/Benchmark/LinearAlgebra/DenseMatrixProduct.cs index 786e26e8..3e9bb88e 100644 --- a/src/Benchmark/LinearAlgebra/DenseMatrixProduct.cs +++ b/src/Benchmark/LinearAlgebra/DenseMatrixProduct.cs @@ -11,60 +11,65 @@ namespace Benchmark.LinearAlgebra { public class DenseMatrixProduct { - readonly Dictionary> _dataMathNet = new Dictionary>(); - private ILinearAlgebraProvider _managed; - private ILinearAlgebraProvider _mkl; - //private ILinearAlgebraProvider _safeProvider; - private ILinearAlgebraProvider _unsafeProvider; - private ILinearAlgebraProvider _experimentalProvider; + readonly Dictionary> _data = new Dictionary>(); + + readonly ILinearAlgebraProvider _managed; + readonly ILinearAlgebraProvider _mkl; + readonly ILinearAlgebraProvider _experimental; + + [Params(8, 64, 128)] + public int M { get; set; } [Params(8, 64, 128)] public int N { get; set; } + static string Key(int m, int n) + { + return $"{m}x{n}"; + } + public DenseMatrixProduct() { + foreach (var m in new[] {8, 64, 128}) foreach (var n in new[] {8, 64, 128}) { - _dataMathNet[n] = Matrix.Build.Random(n, n); + var key = Key(m, n); + _data[key] = Matrix.Build.Random(m, n); } Control.NativeProviderPath = @"..\..\..\..\out\MKL\Windows\"; _managed = new ManagedLinearAlgebraProvider(); _mkl = new MklLinearAlgebraProvider(); - //_safeProvider = new SafeProvider(); - _unsafeProvider = new UnsafeProvider(); - _experimentalProvider = new ExperimentalProvider(); + _experimental = new ExperimentalProvider(); _managed.InitializeVerify(); _mkl.InitializeVerify(); - //_safeProvider.InitializeVerify(); - _unsafeProvider.InitializeVerify(); - _experimentalProvider.InitializeVerify(); + _experimental.InitializeVerify(); + //Verify(); + } + + private void Verify() + { + M = 8; N = 8; var resultMkl = MathNet().ToRowArrays(); var resultManaged = MathNetManaged().ToRowArrays(); - var resultUnsafe = MathNetExtraUnsafe().ToRowArrays(); - var resultExperimental = MathNetExtraExperimental().ToRowArrays(); + var resultExperimental = MathNetExperimental().ToRowArrays(); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (!resultMkl[i][j].AlmostEqual(resultManaged[i][j], 1e-14)) { - throw new Exception(string.Format("Managed [{0}][{1}] {2} != {3}", i, j, resultManaged[i][j], resultMkl[i][j])); - } - if (!resultMkl[i][j].AlmostEqual(resultUnsafe[i][j], 1e-14)) - { - throw new Exception(string.Format("Unsafe [{0}][{1}] {2} != {3}", i, j, resultUnsafe[i][j], resultMkl[i][j])); + throw new Exception($"Managed [{i}][{j}] {resultManaged[i][j]} != {resultMkl[i][j]}"); } if (!resultMkl[i][j].AlmostEqual(resultExperimental[i][j], 1e-14)) { - throw new Exception(string.Format("Experimental [{0}][{1}] {2} != {3}", i, j, resultExperimental[i][j], resultMkl[i][j])); + throw new Exception($"Experimental [{i}][{j}] {resultExperimental[i][j]} != {resultMkl[i][j]}"); } } } - Console.WriteLine("Results OK"); } [Setup] @@ -76,35 +81,21 @@ namespace Benchmark.LinearAlgebra public Matrix MathNet() { Control.LinearAlgebraProvider = _mkl; - return _dataMathNet[N]*_dataMathNet[N]; + return _data[Key(M, N)] *_data[Key(M, N)].Transpose(); } [Benchmark(OperationsPerInvoke = 1)] public Matrix MathNetManaged() { Control.LinearAlgebraProvider = _managed; - return _dataMathNet[N]*_dataMathNet[N]; - } - - //[Benchmark(OperationsPerInvoke = 1)] - //public Matrix MathNetExtraSafe() - //{ - // Control.LinearAlgebraProvider = _safeProvider; - // return _dataMathNet[N] * _dataMathNet[N]; - //} - - [Benchmark(OperationsPerInvoke = 1)] - public Matrix MathNetExtraUnsafe() - { - Control.LinearAlgebraProvider = _unsafeProvider; - return _dataMathNet[N] * _dataMathNet[N]; + return _data[Key(M, N)] *_data[Key(M, N)].Transpose(); } [Benchmark(OperationsPerInvoke = 1)] - public Matrix MathNetExtraExperimental() + public Matrix MathNetExperimental() { - Control.LinearAlgebraProvider = _experimentalProvider; - return _dataMathNet[N] * _dataMathNet[N]; + Control.LinearAlgebraProvider = _experimental; + return _data[Key(M, N)] *_data[Key(M, N)].Transpose(); } public class SafeProvider : ManagedLinearAlgebraProvider @@ -475,56 +466,54 @@ namespace Benchmark.LinearAlgebra { if (a == null) { - throw new ArgumentNullException("a"); + throw new ArgumentNullException(nameof(a)); } if (b == null) { - throw new ArgumentNullException("b"); + throw new ArgumentNullException(nameof(b)); } if (c == null) { - throw new ArgumentNullException("c"); + throw new ArgumentNullException(nameof(c)); } if (transposeA != Transpose.DontTranspose) { - Swap(ref rowsA, ref columnsA); + var swap = rowsA; + rowsA = columnsA; + columnsA = swap; } if (transposeB != Transpose.DontTranspose) { - Swap(ref rowsB, ref columnsB); + var swap = rowsB; + rowsB = columnsB; + columnsB = swap; } if (columnsA != rowsB) { - throw new ArgumentOutOfRangeException(String.Format("columnsA ({0}) != rowsB ({1})", columnsA, rowsB)); + throw new ArgumentOutOfRangeException($"columnsA ({columnsA}) != rowsB ({rowsB})"); } - if (rowsA*columnsA != a.Length) + if (rowsA * columnsA != a.Length) { - throw new ArgumentOutOfRangeException(String.Format( - "rowsA ({0}) * columnsA ({1}) != a.Length ({2})", - rowsA, columnsA, a.Length)); + throw new ArgumentOutOfRangeException($"rowsA ({rowsA}) * columnsA ({columnsA}) != a.Length ({a.Length})"); } - if (rowsB*columnsB != b.Length) + if (rowsB * columnsB != b.Length) { - throw new ArgumentOutOfRangeException(String.Format( - "rowsB ({0}) * columnsB ({1}) != b.Length ({2})", - rowsB, columnsB, b.Length)); + throw new ArgumentOutOfRangeException($"rowsB ({rowsB}) * columnsB ({columnsB}) != b.Length ({b.Length})"); } - if (rowsA*columnsB != c.Length) + if (rowsA * columnsB != c.Length) { - throw new ArgumentOutOfRangeException(String.Format( - "rowsA ({0}) * columnsB ({1}) != c.Length ({2})", - rowsA, columnsB, c.Length)); + throw new ArgumentOutOfRangeException($"rowsA ({rowsA}) * columnsB ({columnsB}) != c.Length ({c.Length})"); } - // handle the degenerate cases + // handle degenerate cases if (beta == 0.0) { Array.Clear(c, 0, c.Length); @@ -546,23 +535,23 @@ namespace Benchmark.LinearAlgebra columnDataB[i] = GetColumn(transposeB, i, rowsB, columnsB, b); } - var shouldNotParallelize = rowsA + columnsB + columnsA < Control.ParallelizeOrder || - Control.MaxDegreeOfParallelism < 2; + var shouldNotParallelize = rowsA + columnsB + columnsA < Control.ParallelizeOrder || Control.MaxDegreeOfParallelism < 2; if (shouldNotParallelize) { + var row = new double[columnsA]; for (int i = 0; i < rowsA; i++) { - var row = GetRow(transposeA, i, rowsA, columnsA, a); + GetRow(transposeA, i, rowsA, columnsA, a, row); for (int j = 0; j < columnsB; j++) { var col = columnDataB[j]; double sum = 0; for (int ii = 0; ii < row.Length; ii++) { - sum += row[ii]*col[ii]; + sum += row[ii] * col[ii]; } - c[j*rowsA + i] += alpha*sum; + c[j * rowsA + i] += alpha * sum; } } } @@ -570,52 +559,42 @@ namespace Benchmark.LinearAlgebra { CommonParallel.For(0, rowsA, 1, (u, v) => { + var row = new double[columnsA]; for (int i = u; i < v; i++) { - // for each row in a - var row = GetRow(transposeA, i, rowsA, columnsA, a); + GetRow(transposeA, i, rowsA, columnsA, a, row); for (int j = 0; j < columnsB; j++) { var column = columnDataB[j]; double sum = 0; for (int ii = 0; ii < row.Length; ii++) { - sum += row[ii]*column[ii]; + sum += row[ii] * column[ii]; } - c[j*rowsA + i] += alpha*sum; + c[j * rowsA + i] += alpha * sum; } } }); } } - static void Swap(ref int first, ref int second) - { - var prior = first; - first = second; - second = prior; - } - /// /// Assumes that and have already been transposed. /// - static double[] GetRow(Transpose transpose, int rowindx, int numRows, int numCols, double[] matrix) + static void GetRow(Transpose transpose, int rowindx, int numRows, int numCols, double[] matrix, double[] row) { - var ret = new double[numCols]; if (transpose == Transpose.DontTranspose) { for (int i = 0; i < numCols; i++) { - ret[i] = matrix[(i*numRows) + rowindx]; + row[i] = matrix[(i * numRows) + rowindx]; } } else { - Array.Copy(matrix, rowindx*numCols, ret, 0, numCols); + Array.Copy(matrix, rowindx * numCols, row, 0, numCols); } - - return ret; } /// @@ -626,13 +605,13 @@ namespace Benchmark.LinearAlgebra var ret = new double[numRows]; if (transpose == Transpose.DontTranspose) { - Array.Copy(matrix, colindx*numRows, ret, 0, numRows); + Array.Copy(matrix, colindx * numRows, ret, 0, numRows); } else { for (int i = 0; i < numRows; i++) { - ret[i] = matrix[(i*numCols) + colindx]; + ret[i] = matrix[(i * numCols) + colindx]; } } diff --git a/src/Benchmark/Program.cs b/src/Benchmark/Program.cs index 06bfb9e0..5af19a1f 100644 --- a/src/Benchmark/Program.cs +++ b/src/Benchmark/Program.cs @@ -1,4 +1,6 @@ using System; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnostics.Windows; using BenchmarkDotNet.Running; using MathNet.Numerics; @@ -12,13 +14,11 @@ namespace Benchmark Console.WriteLine("Linear Algebra: " + Control.LinearAlgebraProvider); Console.WriteLine("FFT: " + Control.FourierTransformProvider); - //var config = ManualConfig.Create(DefaultConfig.Instance); - //var config = new BenchmarkConfig(); - - //.With(new MemoryDiagnoser(), new InliningDiagnoser()); + var config = ManualConfig.Create(DefaultConfig.Instance) + .With(new MemoryDiagnoser()); //, new InliningDiagnoser()); //BenchmarkRunner.Run(config); - BenchmarkRunner.Run(); + BenchmarkRunner.Run(config); //Benchmark(new LinearAlgebra.DenseVectorAdd(10000000,1), 10, "Large (10'000'000) - 10x1 iterations"); //Benchmark(new LinearAlgebra.DenseVectorAdd(100,1000), 100, "Small (100) - 100x1000 iterations");