forked from tsai/mathnet-numerics
14 changed files with 130 additions and 149 deletions
@ -1,109 +1,62 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Generic; |
|||
using BenchmarkDotNet.Attributes; |
|||
using MathNet.Numerics; |
|||
using MathNet.Numerics.LinearAlgebra; |
|||
using MathNet.Numerics.Providers.LinearAlgebra; |
|||
using MathNet.Numerics.Providers.LinearAlgebra.Mkl; |
|||
using MathNet.Numerics.Threading; |
|||
|
|||
namespace Benchmark.LinearAlgebra |
|||
{ |
|||
|
|||
//BenchmarkRunner.Run<LinearAlgebra.DenseMatrixProduct>(config);
|
|||
//Benchmark(new DenseMatrixProduct(10,100), 100, "10 - 100x100 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(25, 100), 100, "25 - 100x100 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(50, 10), 100, "50 - 100x10 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(100, 10), 100, "100 - 100x10 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(250, 1), 10, "250 - 10x1 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(500,1), 10, "500 - 10x1 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(1000,1), 2, "1000 - 2x1 iterations");
|
|||
|
|||
public class DenseMatrixProduct |
|||
{ |
|||
readonly Dictionary<string, Matrix<double>> _data = new Dictionary<string, Matrix<double>>(); |
|||
|
|||
readonly ILinearAlgebraProvider _mathnetMkl; |
|||
readonly ILinearAlgebraProvider _mathnetManaged; |
|||
//readonly ILinearAlgebraProvider _mathnetExperimental;
|
|||
|
|||
[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}"; |
|||
} |
|||
[Params(Provider.Managed, Provider.NativeMKLAutoHigh, Provider.NativeMKLAvx2High)] |
|||
public Provider Provider { get; set; } |
|||
|
|||
public DenseMatrixProduct() |
|||
{ |
|||
foreach (var m in new[] {8, 64, 128}) |
|||
foreach (var n in new[] {8, 64, 128}) |
|||
foreach (var m in new[] { 8, 64, 128 }) |
|||
foreach (var n in new[] { 8, 64, 128 }) |
|||
{ |
|||
var key = Key(m, n); |
|||
_data[key] = Matrix<double>.Build.Random(m, n); |
|||
} |
|||
|
|||
Control.NativeProviderPath = @"..\..\..\..\out\MKL\Windows\"; |
|||
_mathnetMkl = LinearAlgebraControl.CreateNativeMKL(); |
|||
_mathnetManaged = LinearAlgebraControl.CreateManaged(); |
|||
//_mathnetExperimental = new ManagedLinearAlgebraProvider(Variation.Experimental);
|
|||
|
|||
_mathnetMkl.InitializeVerify(); |
|||
_mathnetManaged.InitializeVerify(); |
|||
//_mathnetExperimental.InitializeVerify();
|
|||
} |
|||
|
|||
public void Verify() |
|||
static string Key(int m, int n) |
|||
{ |
|||
M = 8; |
|||
N = 8; |
|||
var resultMkl = MathNetMKL().ToRowArrays(); |
|||
var resultManaged = MathNetManaged().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($"Managed [{i}][{j}] {resultManaged[i][j]} != {resultMkl[i][j]}"); |
|||
} |
|||
//if (!resultMkl[i][j].AlmostEqual(resultExperimental[i][j], 1e-14))
|
|||
//{
|
|||
// throw new Exception($"Experimental [{i}][{j}] {resultExperimental[i][j]} != {resultMkl[i][j]}");
|
|||
//}
|
|||
} |
|||
} |
|||
return $"{m}x{n}"; |
|||
} |
|||
|
|||
[Benchmark(OperationsPerInvoke = 1)] |
|||
public Matrix<double> MathNetMKL() |
|||
[GlobalSetup] |
|||
public void Setup() |
|||
{ |
|||
LinearAlgebraControl.Provider = _mathnetMkl; |
|||
if (M != N) |
|||
{ |
|||
return _data[Key(M, N)].TransposeAndMultiply(_data[Key(M, N)]); |
|||
} |
|||
|
|||
return _data[Key(M, N)]*_data[Key(M, N)]; |
|||
Providers.ForceProvider(Provider); |
|||
} |
|||
|
|||
[Benchmark(OperationsPerInvoke = 1)] |
|||
public Matrix<double> MathNetManaged() |
|||
public Matrix<double> Product() |
|||
{ |
|||
LinearAlgebraControl.Provider = _mathnetManaged; |
|||
if (M != N) |
|||
{ |
|||
return _data[Key(M, N)].TransposeAndMultiply(_data[Key(M, N)]); |
|||
} |
|||
|
|||
return _data[Key(M, N)] * _data[Key(M, N)]; |
|||
return _data[Key(M, N)]*_data[Key(M, N)]; |
|||
} |
|||
|
|||
//[Benchmark(OperationsPerInvoke = 1)]
|
|||
//public Matrix<double> MathNetExperimental()
|
|||
//{
|
|||
// LinearAlgebraControl.Provider = _mathnetExperimental;
|
|||
// if (M != N)
|
|||
// {
|
|||
// return _data[Key(M, N)].TransposeAndMultiply(_data[Key(M, N)]);
|
|||
// }
|
|||
|
|||
// return _data[Key(M, N)] * _data[Key(M, N)];
|
|||
//}
|
|||
} |
|||
} |
|||
|
|||
@ -1,42 +1,31 @@ |
|||
using System; |
|||
using BenchmarkDotNet.Configs; |
|||
using BenchmarkDotNet.Diagnostics.Windows; |
|||
using BenchmarkDotNet.Jobs; |
|||
using System.Linq; |
|||
using BenchmarkDotNet.Running; |
|||
using MathNet.Numerics; |
|||
using MathNet.Numerics.Providers.FourierTransform; |
|||
using MathNet.Numerics.Providers.LinearAlgebra; |
|||
|
|||
namespace Benchmark |
|||
{ |
|||
public class Program |
|||
{ |
|||
public static void Main() |
|||
public static void Main(string[] args) |
|||
{ |
|||
Providers.ForceNativeMKL(); |
|||
Console.WriteLine(Control.Describe()); |
|||
foreach (var provider in Enum.GetValues(typeof(Provider)).Cast<Provider>()) |
|||
{ |
|||
Providers.ForceProvider(provider); |
|||
Console.WriteLine($"{provider}: LA={LinearAlgebraControl.Provider}, FFT={FourierTransformControl.Provider}"); |
|||
} |
|||
|
|||
var subject = new LinearAlgebra.DenseMatrixProduct(); |
|||
subject.Verify(); |
|||
Console.WriteLine("Verified."); |
|||
var switcher = new BenchmarkSwitcher( |
|||
new[] |
|||
{ |
|||
typeof(Transforms.FFT), |
|||
typeof(LinearAlgebra.DenseMatrixProduct), |
|||
}); |
|||
|
|||
var config = ManualConfig.Create(DefaultConfig.Instance); |
|||
config.Add(Job.RyuJitX64, Job.LegacyJitX86); |
|||
//config.Add(new MemoryDiagnoser());
|
|||
|
|||
BenchmarkRunner.Run<Transforms.FFT>(config); |
|||
//BenchmarkRunner.Run<LinearAlgebra.DenseMatrixProduct>(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");
|
|||
|
|||
//DenseMatrixProduct.Verify(5);
|
|||
//DenseMatrixProduct.Verify(100);
|
|||
//Benchmark(new DenseMatrixProduct(10,100), 100, "10 - 100x100 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(25, 100), 100, "25 - 100x100 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(50, 10), 100, "50 - 100x10 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(100, 10), 100, "100 - 100x10 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(250, 1), 10, "250 - 10x1 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(500,1), 10, "500 - 10x1 iterations");
|
|||
//Benchmark(new DenseMatrixProduct(1000,1), 2, "1000 - 2x1 iterations");
|
|||
switcher.Run(args); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,21 +1,45 @@ |
|||
using MathNet.Numerics; |
|||
using MathNet.Numerics.Providers.Common.Mkl; |
|||
|
|||
namespace Benchmark |
|||
{ |
|||
public enum Provider : int |
|||
{ |
|||
Managed = 0, |
|||
NativeMKLAutoHigh = 1, |
|||
NativeMKLAutoLow = 2, |
|||
NativeMKLAvx2High = 3, |
|||
NativeMKLAvx2Low = 4, |
|||
NativeOpenBLAS = 5 |
|||
} |
|||
|
|||
public static class Providers |
|||
{ |
|||
public static void ForceNativeMKL() |
|||
public static void ForceProvider(Provider provider) |
|||
{ |
|||
//Control.NativeProviderPath = @"C:\Triage\NATIVE-Win\";
|
|||
Control.NativeProviderPath = @"..\..\..\..\out\MKL\Windows\"; |
|||
Control.UseNativeMKL(); |
|||
} |
|||
//Control.NativeProviderPath = @"..\..\..\..\out\MKL\Windows\";
|
|||
|
|||
public static void ForceOpenBLAS() |
|||
{ |
|||
//Control.NativeProviderPath = @"C:\Triage\NATIVE-Win\";
|
|||
Control.NativeProviderPath = @"..\..\..\..\out\OpenBLAS\Windows\"; |
|||
Control.UseNativeOpenBLAS(); |
|||
switch (provider) |
|||
{ |
|||
case Provider.Managed: |
|||
Control.UseManaged(); |
|||
break; |
|||
case Provider.NativeMKLAutoHigh: |
|||
Control.UseNativeMKL(MklConsistency.Auto, MklPrecision.Double, MklAccuracy.High); |
|||
break; |
|||
case Provider.NativeMKLAutoLow: |
|||
Control.UseNativeMKL(MklConsistency.Auto, MklPrecision.Double, MklAccuracy.Low); |
|||
break; |
|||
case Provider.NativeMKLAvx2High: |
|||
Control.UseNativeMKL(MklConsistency.AVX2, MklPrecision.Double, MklAccuracy.High); |
|||
break; |
|||
case Provider.NativeMKLAvx2Low: |
|||
Control.UseNativeMKL(MklConsistency.AVX2, MklPrecision.Double, MklAccuracy.Low); |
|||
break; |
|||
case Provider.NativeOpenBLAS: |
|||
Control.UseNativeOpenBLAS(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,51 +1,62 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Numerics; |
|||
using System.Numerics; |
|||
using BenchmarkDotNet.Attributes; |
|||
using BenchmarkDotNet.Configs; |
|||
using BenchmarkDotNet.Environments; |
|||
using BenchmarkDotNet.Jobs; |
|||
using MathNet.Numerics; |
|||
using MathNet.Numerics.IntegralTransforms; |
|||
|
|||
namespace Benchmark.Transforms |
|||
{ |
|||
[Config(typeof(Config))] |
|||
public class FFT |
|||
{ |
|||
readonly Dictionary<int, Complex[]> _data = new Dictionary<int, Complex[]>(); |
|||
|
|||
[Params(32, 64, 128, 1024, 8192, 65536)] |
|||
public int N { get; set; } |
|||
|
|||
public FFT() |
|||
class Config : ManualConfig |
|||
{ |
|||
var realSinusoidal = Generate.Sinusoidal(65536, 32, -2.0, 2.0); |
|||
var imagSawtooth = Generate.Sawtooth(65536, 32, -20.0, 20.0); |
|||
var signal = Generate.Map2(realSinusoidal, imagSawtooth, (r, i) => new Complex(r, i)); |
|||
foreach (var n in new[] { 32, 64, 128, 1024, 8192, 65536 }) |
|||
public Config() |
|||
{ |
|||
var s = new Complex[n]; |
|||
Array.Copy(signal, 0, s, 0, n); |
|||
_data[n] = s; |
|||
Add( |
|||
new Job("CLR RyuJit x64", RunMode.Default, EnvMode.RyuJitX64) |
|||
{ |
|||
Env = { Runtime = Runtime.Clr, Platform = Platform.X64 } |
|||
}, |
|||
new Job("CLR RyuJit x86", RunMode.Default, EnvMode.RyuJitX86) |
|||
{ |
|||
Env = { Runtime = Runtime.Clr, Platform = Platform.X86 } |
|||
}, |
|||
new Job("CLR LegacyJit x64", RunMode.Default, EnvMode.LegacyJitX64) |
|||
{ |
|||
Env = { Runtime = Runtime.Clr, Platform = Platform.X64 } |
|||
}, |
|||
new Job("CLR LegacyJit x86", RunMode.Default, EnvMode.LegacyJitX86) |
|||
{ |
|||
Env = { Runtime = Runtime.Clr, Platform = Platform.X86 } |
|||
}); |
|||
} |
|||
|
|||
Providers.ForceNativeMKL(); |
|||
} |
|||
|
|||
[Setup] |
|||
public void Setup() |
|||
{ |
|||
} |
|||
[Params(32, 128)] //, 64, 1024, 8192, 65536)]
|
|||
public int N { get; set; } |
|||
|
|||
[Params(Provider.Managed, Provider.NativeMKLAutoHigh, Provider.NativeMKLAvx2High)] |
|||
public Provider Provider { get; set; } |
|||
|
|||
[Benchmark(Baseline = true, OperationsPerInvoke = 2)] |
|||
public void Managed() |
|||
Complex[] _data; |
|||
|
|||
[GlobalSetup] |
|||
public void Setup() |
|||
{ |
|||
Fourier.Radix2Forward(_data[N], FourierOptions.NoScaling); |
|||
Fourier.Radix2Inverse(_data[N], FourierOptions.NoScaling); |
|||
Providers.ForceProvider(Provider); |
|||
var realSinusoidal = Generate.Sinusoidal(N, 32, -2.0, 2.0); |
|||
var imagSawtooth = Generate.Sawtooth(N, 32, -20.0, 20.0); |
|||
_data = Generate.Map2(realSinusoidal, imagSawtooth, (r, i) => new Complex(r, i)); |
|||
} |
|||
|
|||
[Benchmark(OperationsPerInvoke = 2)] |
|||
public void NativeMKL() |
|||
public void Transform() |
|||
{ |
|||
Fourier.Forward(_data[N], FourierOptions.NoScaling); |
|||
Fourier.Inverse(_data[N], FourierOptions.NoScaling); |
|||
Fourier.Forward(_data, FourierOptions.NoScaling); |
|||
Fourier.Inverse(_data, FourierOptions.NoScaling); |
|||
} |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue