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 BenchmarkDotNet.Attributes; |
||||
using MathNet.Numerics; |
|
||||
using MathNet.Numerics.LinearAlgebra; |
using MathNet.Numerics.LinearAlgebra; |
||||
using MathNet.Numerics.Providers.LinearAlgebra; |
|
||||
using MathNet.Numerics.Providers.LinearAlgebra.Mkl; |
|
||||
using MathNet.Numerics.Threading; |
|
||||
|
|
||||
namespace Benchmark.LinearAlgebra |
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 |
public class DenseMatrixProduct |
||||
{ |
{ |
||||
readonly Dictionary<string, Matrix<double>> _data = new Dictionary<string, Matrix<double>>(); |
readonly Dictionary<string, Matrix<double>> _data = new Dictionary<string, Matrix<double>>(); |
||||
|
|
||||
readonly ILinearAlgebraProvider _mathnetMkl; |
|
||||
readonly ILinearAlgebraProvider _mathnetManaged; |
|
||||
//readonly ILinearAlgebraProvider _mathnetExperimental;
|
|
||||
|
|
||||
[Params(8, 64, 128)] |
[Params(8, 64, 128)] |
||||
public int M { get; set; } |
public int M { get; set; } |
||||
|
|
||||
[Params(8, 64, 128)] |
[Params(8, 64, 128)] |
||||
public int N { get; set; } |
public int N { get; set; } |
||||
|
|
||||
static string Key(int m, int n) |
[Params(Provider.Managed, Provider.NativeMKLAutoHigh, Provider.NativeMKLAvx2High)] |
||||
{ |
public Provider Provider { get; set; } |
||||
return $"{m}x{n}"; |
|
||||
} |
|
||||
|
|
||||
public DenseMatrixProduct() |
public DenseMatrixProduct() |
||||
{ |
{ |
||||
foreach (var m in new[] {8, 64, 128}) |
foreach (var m in new[] { 8, 64, 128 }) |
||||
foreach (var n in new[] {8, 64, 128}) |
foreach (var n in new[] { 8, 64, 128 }) |
||||
{ |
{ |
||||
var key = Key(m, n); |
var key = Key(m, n); |
||||
_data[key] = Matrix<double>.Build.Random(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; |
return $"{m}x{n}"; |
||||
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]}");
|
|
||||
//}
|
|
||||
} |
|
||||
} |
|
||||
} |
} |
||||
|
|
||||
[Benchmark(OperationsPerInvoke = 1)] |
[GlobalSetup] |
||||
public Matrix<double> MathNetMKL() |
public void Setup() |
||||
{ |
{ |
||||
LinearAlgebraControl.Provider = _mathnetMkl; |
Providers.ForceProvider(Provider); |
||||
if (M != N) |
|
||||
{ |
|
||||
return _data[Key(M, N)].TransposeAndMultiply(_data[Key(M, N)]); |
|
||||
} |
|
||||
|
|
||||
return _data[Key(M, N)]*_data[Key(M, N)]; |
|
||||
} |
} |
||||
|
|
||||
[Benchmark(OperationsPerInvoke = 1)] |
[Benchmark(OperationsPerInvoke = 1)] |
||||
public Matrix<double> MathNetManaged() |
public Matrix<double> Product() |
||||
{ |
{ |
||||
LinearAlgebraControl.Provider = _mathnetManaged; |
|
||||
if (M != N) |
if (M != N) |
||||
{ |
{ |
||||
return _data[Key(M, N)].TransposeAndMultiply(_data[Key(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 System; |
||||
using BenchmarkDotNet.Configs; |
using System.Linq; |
||||
using BenchmarkDotNet.Diagnostics.Windows; |
|
||||
using BenchmarkDotNet.Jobs; |
|
||||
using BenchmarkDotNet.Running; |
using BenchmarkDotNet.Running; |
||||
using MathNet.Numerics; |
using MathNet.Numerics; |
||||
|
using MathNet.Numerics.Providers.FourierTransform; |
||||
|
using MathNet.Numerics.Providers.LinearAlgebra; |
||||
|
|
||||
namespace Benchmark |
namespace Benchmark |
||||
{ |
{ |
||||
public class Program |
public class Program |
||||
{ |
{ |
||||
public static void Main() |
public static void Main(string[] args) |
||||
{ |
{ |
||||
Providers.ForceNativeMKL(); |
|
||||
Console.WriteLine(Control.Describe()); |
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(); |
var switcher = new BenchmarkSwitcher( |
||||
subject.Verify(); |
new[] |
||||
Console.WriteLine("Verified."); |
{ |
||||
|
typeof(Transforms.FFT), |
||||
|
typeof(LinearAlgebra.DenseMatrixProduct), |
||||
|
}); |
||||
|
|
||||
var config = ManualConfig.Create(DefaultConfig.Instance); |
switcher.Run(args); |
||||
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");
|
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,21 +1,45 @@ |
|||||
using MathNet.Numerics; |
using MathNet.Numerics; |
||||
|
using MathNet.Numerics.Providers.Common.Mkl; |
||||
|
|
||||
namespace Benchmark |
namespace Benchmark |
||||
{ |
{ |
||||
|
public enum Provider : int |
||||
|
{ |
||||
|
Managed = 0, |
||||
|
NativeMKLAutoHigh = 1, |
||||
|
NativeMKLAutoLow = 2, |
||||
|
NativeMKLAvx2High = 3, |
||||
|
NativeMKLAvx2Low = 4, |
||||
|
NativeOpenBLAS = 5 |
||||
|
} |
||||
|
|
||||
public static class Providers |
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.NativeProviderPath = @"..\..\..\..\out\MKL\Windows\"; |
|
||||
Control.UseNativeMKL(); |
|
||||
} |
|
||||
|
|
||||
public static void ForceOpenBLAS() |
switch (provider) |
||||
{ |
{ |
||||
//Control.NativeProviderPath = @"C:\Triage\NATIVE-Win\";
|
case Provider.Managed: |
||||
Control.NativeProviderPath = @"..\..\..\..\out\OpenBLAS\Windows\"; |
Control.UseManaged(); |
||||
Control.UseNativeOpenBLAS(); |
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.Numerics; |
||||
using System.Collections.Generic; |
|
||||
using System.Numerics; |
|
||||
using BenchmarkDotNet.Attributes; |
using BenchmarkDotNet.Attributes; |
||||
|
using BenchmarkDotNet.Configs; |
||||
|
using BenchmarkDotNet.Environments; |
||||
|
using BenchmarkDotNet.Jobs; |
||||
using MathNet.Numerics; |
using MathNet.Numerics; |
||||
using MathNet.Numerics.IntegralTransforms; |
using MathNet.Numerics.IntegralTransforms; |
||||
|
|
||||
namespace Benchmark.Transforms |
namespace Benchmark.Transforms |
||||
{ |
{ |
||||
|
[Config(typeof(Config))] |
||||
public class FFT |
public class FFT |
||||
{ |
{ |
||||
readonly Dictionary<int, Complex[]> _data = new Dictionary<int, Complex[]>(); |
class Config : ManualConfig |
||||
|
|
||||
[Params(32, 64, 128, 1024, 8192, 65536)] |
|
||||
public int N { get; set; } |
|
||||
|
|
||||
public FFT() |
|
||||
{ |
{ |
||||
var realSinusoidal = Generate.Sinusoidal(65536, 32, -2.0, 2.0); |
public Config() |
||||
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 }) |
|
||||
{ |
{ |
||||
var s = new Complex[n]; |
Add( |
||||
Array.Copy(signal, 0, s, 0, n); |
new Job("CLR RyuJit x64", RunMode.Default, EnvMode.RyuJitX64) |
||||
_data[n] = s; |
{ |
||||
|
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] |
[Params(32, 128)] //, 64, 1024, 8192, 65536)]
|
||||
public void Setup() |
public int N { get; set; } |
||||
{ |
|
||||
} |
[Params(Provider.Managed, Provider.NativeMKLAutoHigh, Provider.NativeMKLAvx2High)] |
||||
|
public Provider Provider { get; set; } |
||||
|
|
||||
[Benchmark(Baseline = true, OperationsPerInvoke = 2)] |
Complex[] _data; |
||||
public void Managed() |
|
||||
|
[GlobalSetup] |
||||
|
public void Setup() |
||||
{ |
{ |
||||
Fourier.Radix2Forward(_data[N], FourierOptions.NoScaling); |
Providers.ForceProvider(Provider); |
||||
Fourier.Radix2Inverse(_data[N], FourierOptions.NoScaling); |
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)] |
[Benchmark(OperationsPerInvoke = 2)] |
||||
public void NativeMKL() |
public void Transform() |
||||
{ |
{ |
||||
Fourier.Forward(_data[N], FourierOptions.NoScaling); |
Fourier.Forward(_data, FourierOptions.NoScaling); |
||||
Fourier.Inverse(_data[N], FourierOptions.NoScaling); |
Fourier.Inverse(_data, FourierOptions.NoScaling); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue