Browse Source

Bench: revive benchmarking project, for FFT

pull/445/head
Christoph Ruegg 10 years ago
parent
commit
0be3925a8c
  1. 34
      Benchmark.sln
  2. 38
      Performance.sln
  3. 4
      paket.dependencies
  4. 23
      paket.lock
  5. 173
      src/Benchmark/Benchmark.csproj
  6. 48
      src/Benchmark/FFT.cs
  7. 556
      src/Benchmark/LinearAlgebra/DenseMatrixProduct.cs
  8. 149
      src/Benchmark/LinearAlgebra/DenseVectorAdd.cs
  9. 35
      src/Benchmark/Program.cs
  10. 0
      src/Benchmark/Properties/AssemblyInfo.cs
  11. 2
      src/Benchmark/paket.references
  12. 1
      src/Numerics/Numerics.csproj
  13. 557
      src/Performance/LinearAlgebra/DenseMatrixProduct.cs
  14. 150
      src/Performance/LinearAlgebra/DenseVectorAdd.cs
  15. 109
      src/Performance/Performance.csproj
  16. 52
      src/Performance/Program.cs
  17. 3
      src/Performance/paket.references

34
Benchmark.sln

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmark", "src\Benchmark\Benchmark.csproj", "{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "src\Numerics\Numerics.csproj", "{B7CAE5F4-A23F-4438-B5BE-41226618B695}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8DFE7990-CAC9-4BCC-A1D7-F86F0892DD84}"
ProjectSection(SolutionItems) = preProject
paket.dependencies = paket.dependencies
paket.lock = paket.lock
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release|x64.ActiveCfg = Release|x64
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release|x64.Build.0 = Release|x64
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release|x86.ActiveCfg = Release|x64
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release|x86.Build.0 = Release|x64
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|x64.ActiveCfg = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|x64.Build.0 = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|x86.ActiveCfg = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

38
Performance.sln

@ -1,38 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Performance", "src\Performance\Performance.csproj", "{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "src\Numerics\Numerics.csproj", "{B7CAE5F4-A23F-4438-B5BE-41226618B695}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release (No MKL)|Any CPU = Release (No MKL)|Any CPU
Release|Any CPU = Release|Any CPU
Release-Signed|Any CPU = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release (No MKL)|Any CPU.ActiveCfg = Release (No MKL)|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release (No MKL)|Any CPU.Build.0 = Release (No MKL)|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release|Any CPU.Build.0 = Release|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release-Signed|Any CPU.ActiveCfg = Release|Any CPU
{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}.Release-Signed|Any CPU.Build.0 = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release (No MKL)|Any CPU.ActiveCfg = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release (No MKL)|Any CPU.Build.0 = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|Any CPU.Build.0 = Release|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

4
paket.dependencies

@ -23,5 +23,5 @@ group Data
group Benchmark
source http://www.nuget.org/api/v2
nuget BenchShark 1.0.0
nuget ConsoleDump 0.6.0.1
framework: net45
nuget BenchmarkDotNet

23
paket.lock

@ -7,10 +7,29 @@ GITHUB
src/FsUnit.NUnit/FsUnit.fs (43086ca8981c7642c1067ad5e9de80caf73ba4ec)
src/FsUnit.NUnit/FsUnitTyped.fs (43086ca8981c7642c1067ad5e9de80caf73ba4ec)
GROUP Benchmark
FRAMEWORK: NET45
NUGET
remote: http://www.nuget.org/api/v2
BenchShark (1.0)
ConsoleDump (0.6.0.1)
BenchmarkDotNet (0.9.9)
BenchmarkDotNet.Toolchains.Roslyn (>= 0.9.9)
BenchmarkDotNet.Core (0.9.9)
System.Threading.Tasks.Extensions (>= 4.0)
BenchmarkDotNet.Toolchains.Roslyn (0.9.9)
BenchmarkDotNet.Core (>= 0.9.9)
Microsoft.CodeAnalysis.CSharp (>= 1.3.2)
System.Threading.Tasks (>= 4.0)
Microsoft.CodeAnalysis.Analyzers (1.1)
Microsoft.CodeAnalysis.Common (1.3.2)
Microsoft.CodeAnalysis.Analyzers (>= 1.1)
System.Collections.Immutable (>= 1.1.37)
System.Reflection.Metadata (>= 1.2)
Microsoft.CodeAnalysis.CSharp (1.3.2)
Microsoft.CodeAnalysis.Common (1.3.2)
System.Collections.Immutable (1.2)
System.Reflection.Metadata (1.2)
System.Collections.Immutable (>= 1.2)
System.Threading.Tasks (4.0.11)
System.Threading.Tasks.Extensions (4.0)
GROUP Build
NUGET

173
src/Benchmark/Benchmark.csproj

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Benchmark</RootNamespace>
<AssemblyName>Benchmark</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NATIVE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NATIVE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FFT.cs" />
<Compile Include="LinearAlgebra\DenseVectorAdd.cs" />
<Compile Include="LinearAlgebra\DenseMatrixProduct.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="paket.references" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Numerics\Numerics.csproj">
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="BenchmarkDotNet">
<HintPath>..\..\packages\benchmark\BenchmarkDotNet\lib\net45\BenchmarkDotNet.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="BenchmarkDotNet.Core">
<HintPath>..\..\packages\benchmark\BenchmarkDotNet.Core\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
<Reference Include="System.Management">
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn">
<HintPath>..\..\packages\benchmark\BenchmarkDotNet.Toolchains.Roslyn\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<ItemGroup>
<Analyzer Include="..\..\packages\benchmark\Microsoft.CodeAnalysis.Analyzers\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll">
<Paket>True</Paket>
</Analyzer>
<Analyzer Include="..\..\packages\benchmark\Microsoft.CodeAnalysis.Analyzers\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll">
<Paket>True</Paket>
</Analyzer>
</ItemGroup>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="Microsoft.CodeAnalysis">
<HintPath>..\..\packages\benchmark\Microsoft.CodeAnalysis.Common\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="Microsoft.CodeAnalysis.CSharp">
<HintPath>..\..\packages\benchmark\Microsoft.CodeAnalysis.CSharp\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="System.Collections.Immutable">
<HintPath>..\..\packages\benchmark\System.Collections.Immutable\lib\netstandard1.0\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="System.Reflection.Metadata">
<HintPath>..\..\packages\benchmark\System.Reflection.Metadata\lib\netstandard1.1\System.Reflection.Metadata.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v4.5'">
<ItemGroup>
<Reference Include="System.Threading.Tasks.Extensions">
<HintPath>..\..\packages\benchmark\System.Threading.Tasks.Extensions\lib\netstandard1.0\System.Threading.Tasks.Extensions.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
</Project>

48
src/Benchmark/FFT.cs

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;
namespace Benchmark
{
public class FFT
{
readonly Dictionary<int, Complex[]> _data = new Dictionary<int, Complex[]>();
[Params(64, 65, 4096, 4097, 65536, 65537, 1048576, 1048577)]
public int N { get; set; }
[Setup]
public void Setup()
{
var realSinusoidal = Generate.Sinusoidal(1048577, 32, -2.0, 2.0);
var imagSawtooth = Generate.Sawtooth(1048577, 32, -20.0, 20.0);
var signal = Generate.Map2(realSinusoidal, imagSawtooth, (r, i) => new Complex(r, i));
foreach (var n in new[] { 64, 65, 4096, 4097, 65536, 65537, 1048576, 1048577 })
{
var s = new Complex[n];
Array.Copy(signal, 0, s, 0, n);
_data[n] = s;
}
Control.NativeProviderPath = @"C:\Triage\NATIVE-Win\";
Control.UseNativeMKL();
}
[Benchmark(Baseline = true, OperationsPerInvoke = 2)]
public void Managed()
{
Fourier.BluesteinForward(_data[N], FourierOptions.NoScaling);
Fourier.BluesteinInverse(_data[N], FourierOptions.NoScaling);
}
[Benchmark(OperationsPerInvoke = 2)]
public void NativeMKL()
{
Fourier.Forward(_data[N], FourierOptions.NoScaling);
Fourier.Inverse(_data[N], FourierOptions.NoScaling);
}
}
}

556
src/Benchmark/LinearAlgebra/DenseMatrixProduct.cs

@ -0,0 +1,556 @@
using System;
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
{
// public class DenseMatrixProduct
// {
// readonly int _rounds;
// readonly Matrix<double> _a;
// readonly Matrix<double> _b;
// readonly ILinearAlgebraProvider _managed = new ManagedLinearAlgebraProvider();
// readonly ILinearAlgebraProvider _mkl = new MklLinearAlgebraProvider();
// readonly ILinearAlgebraProvider _safeProvider = new SafeProvider();
// readonly ILinearAlgebraProvider _unsafeProvider = new UnsafeProvider();
// readonly ILinearAlgebraProvider _experimentalProvider = new ExperimentalProvider();
// public DenseMatrixProduct(int size, int rounds)
// {
// _rounds = rounds;
// _b = Matrix<double>.Build.Random(size, size);
// _a = Matrix<double>.Build.Random(size, size);
// _managed.InitializeVerify();
// _safeProvider.InitializeVerify();
// _unsafeProvider.InitializeVerify();
// _experimentalProvider.InitializeVerify();
//#if NATIVE
// _mkl.InitializeVerify();
//#endif
// }
// public static void Verify(int size)
// {
// var x = new DenseMatrixProduct(size, 1);
// var managedResult = x.ManagedProvider();
// var mklResult = x.MklProvider();
// var safeResult = x.SafeProvider();
// var unsafeResult = x.UnsafeProvider();
// var experimentalResult = x.ExperimentalProvider();
// Console.WriteLine(managedResult.ToString());
// //Console.WriteLine(mklResult.ToString());
// //Console.WriteLine(safeResult.ToString());
// //Console.WriteLine(unsafeResult.ToString());
// //Console.WriteLine(experimentalResult.ToString());
// if (!managedResult.AlmostEqual(mklResult, 1e-12))
// {
// throw new Exception("MklProvider");
// }
// if (!managedResult.AlmostEqual(safeResult, 1e-12))
// {
// throw new Exception("SafeProvider");
// }
// if (!managedResult.AlmostEqual(unsafeResult, 1e-12))
// {
// throw new Exception("UnsafeProvider");
// }
// if (!managedResult.AlmostEqual(experimentalResult, 1e-12))
// {
// throw new Exception("ExperimentalProvider");
// }
// }
// [BenchSharkTask("ManagedProvider")]
// public Matrix<double> ManagedProvider()
// {
// Control.LinearAlgebraProvider = _managed;
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a*z;
// }
// return z;
// }
// [BenchSharkTask("MklProvider")]
// public Matrix<double> MklProvider()
// {
// Control.LinearAlgebraProvider = _mkl;
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a*z;
// }
// return z;
// }
// [BenchSharkTask("SafeProvider")]
// public Matrix<double> SafeProvider()
// {
// Control.LinearAlgebraProvider = _safeProvider;
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a*z;
// }
// return z;
// }
// [BenchSharkTask("UnsafeProvider")]
// public Matrix<double> UnsafeProvider()
// {
// Control.LinearAlgebraProvider = _unsafeProvider;
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a*z;
// }
// return z;
// }
// [BenchSharkTask("ExperimentalProvider")]
// public Matrix<double> ExperimentalProvider()
// {
// Control.LinearAlgebraProvider = _experimentalProvider;
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a*z;
// }
// return z;
// }
// }
// public class SafeProvider : ManagedLinearAlgebraProvider
// {
// public override void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
// {
// if (rowsX + columnsY <= Control.ParallelizeOrder)
// {
// for (int i = 0; i < rowsX; ++i)
// {
// for (int j = 0; j < columnsY; ++j)
// {
// var jrowsY = j*rowsY;
// double sum = 0.0;
// for (int k = 0; k < columnsX; ++k)
// {
// sum += x[k*rowsX + i]*y[jrowsY + k];
// }
// result[j*rowsX + i] = sum;
// }
// }
// return;
// }
// double[] xdata;
// if (ReferenceEquals(x, result))
// {
// xdata = (double[])x.Clone();
// }
// else
// {
// xdata = x;
// }
// double[] ydata;
// if (ReferenceEquals(y, result))
// {
// ydata = (double[])y.Clone();
// }
// else
// {
// ydata = y;
// }
// Array.Clear(result, 0, result.Length);
// CacheObliviousMatrixMultiply(xdata, 0, 0, ydata, 0, 0, result, 0, 0, rowsX, columnsY, columnsX, rowsX, columnsY, columnsX, 0);
// }
// public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
// {
// if (transposeA == Transpose.DontTranspose && transposeB == Transpose.DontTranspose && alpha == 1.0 && beta == 0.0)
// {
// MatrixMultiply(a, rowsA, columnsA, b, rowsB, columnsB, c);
// return;
// }
// base.MatrixMultiplyWithUpdate(transposeA, transposeB, alpha, a, rowsA, columnsA, b, rowsB, columnsB, beta, c);
// }
// static void CacheObliviousMatrixMultiply(double[] matrixA, int shiftArow, int shiftAcol, double[] matrixB, int shiftBrow, int shiftBcol, double[] result, int shiftCrow, int shiftCcol, int m, int n, int k, int constM, int constN, int constK, int level)
// {
// if (m + n <= Control.ParallelizeOrder)
// {
// for (var m1 = 0; m1 < m; m1++)
// {
// var matArowPos = m1 + shiftArow;
// var matCrowPos = m1 + shiftCrow;
// for (var n1 = 0; n1 < n; ++n1)
// {
// var boffset = ((n1 + shiftBcol)*constK) + shiftBrow;
// double sum = 0;
// for (var k1 = 0; k1 < k; ++k1)
// {
// sum += matrixA[((k1 + shiftAcol)*constM) + matArowPos]*matrixB[boffset + k1];
// }
// result[((n1 + shiftCcol)*constM) + matCrowPos] += sum;
// }
// }
// return;
// }
// // divide and conquer
// int m2 = m/2, n2 = n/2, k2 = k/2;
// level++;
// if (level <= 2)
// {
// CommonParallel.Invoke(
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level));
// CommonParallel.Invoke(
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level));
// }
// else
// {
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level);
// }
// }
// }
// public unsafe class UnsafeProvider : ManagedLinearAlgebraProvider
// {
// public override void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
// {
// if (rowsX + columnsY <= Control.ParallelizeOrder)
// {
// fixed (double* resultPtr = &result[0])
// fixed (double* xPtr = &x[0])
// fixed (double* yPtr = &y[0])
// {
// double* a = xPtr;
// double* c = resultPtr;
// for (int i = 0; i < rowsX; ++i)
// {
// double* b = yPtr;
// double* cj = c;
// for (int j = 0; j < columnsY; ++j)
// {
// double sum = 0.0;
// for (int k = 0; k < columnsX; ++k)
// {
// sum += a[k*rowsX]*b[k];
// }
// *cj = sum;
// cj += rowsX;
// b += rowsY;
// }
// a++;
// c++;
// }
// }
// return;
// }
// double[] xdata;
// if (ReferenceEquals(x, result))
// {
// xdata = (double[])x.Clone();
// }
// else
// {
// xdata = x;
// }
// double[] ydata;
// if (ReferenceEquals(y, result))
// {
// ydata = (double[])y.Clone();
// }
// else
// {
// ydata = y;
// }
// Array.Clear(result, 0, result.Length);
// CacheObliviousMatrixMultiply(xdata, 0, 0, ydata, 0, 0, result, 0, 0, rowsX, columnsY, columnsX, rowsX, columnsY, columnsX, 0);
// }
// public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
// {
// if (transposeA == Transpose.DontTranspose && transposeB == Transpose.DontTranspose && alpha == 1.0 && beta == 0.0)
// {
// MatrixMultiply(a, rowsA, columnsA, b, rowsB, columnsB, c);
// return;
// }
// base.MatrixMultiplyWithUpdate(transposeA, transposeB, alpha, a, rowsA, columnsA, b, rowsB, columnsB, beta, c);
// }
// static void CacheObliviousMatrixMultiply(double[] matrixA, int shiftArow, int shiftAcol, double[] matrixB, int shiftBrow, int shiftBcol, double[] result, int shiftCrow, int shiftCcol, int m, int n, int k, int constM, int constN, int constK, int level)
// {
// if (m + n <= Control.ParallelizeOrder)
// {
// fixed (double* resultPtr = &result[0])
// fixed (double* aPtr = &matrixA[0])
// fixed (double* bPtr = &matrixB[0])
// {
// double* a = aPtr + shiftArow;
// double* c = resultPtr + shiftCrow;
// for (var m1 = 0; m1 < m; m1++)
// {
// for (var n1 = 0; n1 < n; ++n1)
// {
// double* b = bPtr + (n1 + shiftBcol)*constK + shiftBrow;
// double sum = 0;
// for (var k1 = 0; k1 < k; ++k1)
// {
// sum += a[((k1 + shiftAcol)*constM)]*b[k1];
// }
// c[((n1 + shiftCcol)*constM)] += sum;
// }
// a++;
// c++;
// }
// }
// return;
// }
// // divide and conquer
// int m2 = m/2, n2 = n/2, k2 = k/2;
// level++;
// if (level <= 2)
// {
// CommonParallel.Invoke(
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level));
// CommonParallel.Invoke(
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level),
// () => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level));
// }
// else
// {
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level);
// CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level);
// }
// }
// }
// public class ExperimentalProvider : ManagedLinearAlgebraProvider
// {
// public override void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
// {
// MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, rowsX, columnsX, y, rowsY, columnsY, 0.0, result);
// }
// public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
// {
// if (a == null)
// {
// throw new ArgumentNullException("a");
// }
// if (b == null)
// {
// throw new ArgumentNullException("b");
// }
// if (c == null)
// {
// throw new ArgumentNullException("c");
// }
// if (transposeA != Transpose.DontTranspose)
// {
// Swap(ref rowsA, ref columnsA);
// }
// if (transposeB != Transpose.DontTranspose)
// {
// Swap(ref rowsB, ref columnsB);
// }
// if (columnsA != rowsB)
// {
// throw new ArgumentOutOfRangeException(String.Format("columnsA ({0}) != rowsB ({1})", columnsA, rowsB));
// }
// if (rowsA*columnsA != a.Length)
// {
// throw new ArgumentOutOfRangeException(String.Format("rowsA ({0}) * columnsA ({1}) != a.Length ({2})", rowsA, columnsA, a.Length));
// }
// if (rowsB*columnsB != b.Length)
// {
// throw new ArgumentOutOfRangeException(String.Format("rowsB ({0}) * columnsB ({1}) != b.Length ({2})", rowsB, columnsB, b.Length));
// }
// if (rowsA*columnsB != c.Length)
// {
// throw new ArgumentOutOfRangeException(String.Format("rowsA ({0}) * columnsB ({1}) != c.Length ({2})", rowsA, columnsB, c.Length));
// }
// // handle the degenerate cases
// if (beta == 0.0)
// {
// Array.Clear(c, 0, c.Length);
// }
// else if (beta != 1.0)
// {
// ScaleArray(beta, c, c);
// }
// if (alpha == 0.0)
// {
// return;
// }
// // Extract column arrays
// var columnDataB = new double[columnsB][];
// for (int i = 0; i < columnDataB.Length; i++)
// {
// columnDataB[i] = GetColumn(transposeB, i, rowsB, columnsB, b);
// }
// var shouldNotParallelize = rowsA + columnsB + columnsA < Control.ParallelizeOrder || Control.MaxDegreeOfParallelism < 2;
// if (shouldNotParallelize)
// {
// for (int i = 0; i < rowsA; i++)
// {
// var row = GetRow(transposeA, i, rowsA, columnsA, a);
// 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];
// }
// c[j*rowsA + i] += alpha*sum;
// }
// }
// }
// else
// {
// CommonParallel.For(0, rowsA, 1, (u, v) =>
// {
// for (int i = u; i < v; i++)
// {
// // for each row in a
// var row = GetRow(transposeA, i, rowsA, columnsA, a);
// 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];
// }
// c[j*rowsA + i] += alpha*sum;
// }
// }
// });
// }
// }
// static void Swap(ref int first, ref int second)
// {
// var prior = first;
// first = second;
// second = prior;
// }
// /// <summary>
// /// Assumes that <paramref name="numRows"/> and <paramref name="numCols"/> have already been transposed.
// /// </summary>
// static double[] GetRow(Transpose transpose, int rowindx, int numRows, int numCols, double[] matrix)
// {
// var ret = new double[numCols];
// if (transpose == Transpose.DontTranspose)
// {
// for (int i = 0; i < numCols; i++)
// {
// ret[i] = matrix[(i*numRows) + rowindx];
// }
// }
// else
// {
// Array.Copy(matrix, rowindx*numCols, ret, 0, numCols);
// }
// return ret;
// }
// /// <summary>
// /// Assumes that <paramref name="numRows"/> and <paramref name="numCols"/> have already been transposed.
// /// </summary>
// static double[] GetColumn(Transpose transpose, int colindx, int numRows, int numCols, double[] matrix)
// {
// var ret = new double[numRows];
// if (transpose == Transpose.DontTranspose)
// {
// Array.Copy(matrix, colindx*numRows, ret, 0, numRows);
// }
// else
// {
// for (int i = 0; i < numRows; i++)
// {
// ret[i] = matrix[(i*numCols) + colindx];
// }
// }
// return ret;
// }
// }
}

149
src/Benchmark/LinearAlgebra/DenseVectorAdd.cs

@ -0,0 +1,149 @@
using System;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Storage;
using MathNet.Numerics.Providers.LinearAlgebra;
using MathNet.Numerics.Providers.LinearAlgebra.Mkl;
using MathNet.Numerics.Threading;
namespace Benchmark.LinearAlgebra
{
// public class DenseVectorAdd
// {
// readonly int _rounds;
// readonly Vector<double> _a;
// readonly Vector<double> _b;
// readonly ILinearAlgebraProvider _managed = new ManagedLinearAlgebraProvider();
// readonly ILinearAlgebraProvider _mkl = new MklLinearAlgebraProvider();
// public DenseVectorAdd(int size, int rounds)
// {
// _rounds = rounds;
// _b = Vector<double>.Build.Random(size);
// _a = Vector<double>.Build.Random(size);
// _managed.InitializeVerify();
// Control.LinearAlgebraProvider = _managed;
//#if NATIVE
// _mkl.InitializeVerify();
//#endif
// }
// [BenchSharkTask("AddOperator")]
// public Vector<double> AddOperator()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a + z;
// }
// return z;
// }
// [BenchSharkTask("Map2")]
// public Vector<double> Map2()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// z = _a.Map2((u, v) => u + v, z);
// }
// return z;
// }
// [BenchSharkTask("Loop")]
// public Vector<double> Loop()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
// var az = ((DenseVectorStorage<double>)z.Storage).Data;
// var ar = new Double[aa.Length];
// for (int k = 0; k < ar.Length; k++)
// {
// ar[k] = aa[k] + az[k];
// }
// z = Vector<double>.Build.Dense(ar);
// }
// return z;
// }
// [BenchSharkTask("ParallelLoop4096")]
// public Vector<double> ParallelLoop4096()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
// var az = ((DenseVectorStorage<double>)z.Storage).Data;
// var ar = new Double[aa.Length];
// CommonParallel.For(0, ar.Length, 4096, (u, v) =>
// {
// for (int k = u; k < v; k++)
// {
// ar[k] = aa[k] + az[k];
// }
// });
// z = Vector<double>.Build.Dense(ar);
// }
// return z;
// }
// [BenchSharkTask("ParallelLoop32768")]
// public Vector<double> ParallelLoop32768()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
// var az = ((DenseVectorStorage<double>)z.Storage).Data;
// var ar = new Double[aa.Length];
// CommonParallel.For(0, ar.Length, 32768, (u, v) =>
// {
// for (int k = u; k < v; k++)
// {
// ar[k] = aa[k] + az[k];
// }
// });
// z = Vector<double>.Build.Dense(ar);
// }
// return z;
// }
// [BenchSharkTask("ManagedProvider")]
// public Vector<double> ManagedProvider()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
// var az = ((DenseVectorStorage<double>)z.Storage).Data;
// var ar = new Double[aa.Length];
// _managed.AddArrays(aa, az, ar);
// z = Vector<double>.Build.Dense(ar);
// }
// return z;
// }
//#if NATIVEMKL
// [BenchSharkTask("MklProvider")]
// public Vector<double> MklProvider()
// {
// var z = _b;
// for (int i = 0; i < _rounds; i++)
// {
// var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
// var az = ((DenseVectorStorage<double>)z.Storage).Data;
// var ar = new Double[aa.Length];
// _mkl.AddArrays(aa, az, ar);
// z = Vector<double>.Build.Dense(ar);
// }
// return z;
// }
//#endif
// }
}

35
src/Benchmark/Program.cs

@ -0,0 +1,35 @@
using System;
using BenchmarkDotNet.Running;
using MathNet.Numerics;
namespace Benchmark
{
public class Program
{
public static void Main()
{
//Control.NativeProviderPath = @"..\..\..\..\out\MKL\Windows\";
Control.NativeProviderPath = @"C:\Triage\NATIVE-Win\";
Console.WriteLine("Providers:");
if (Control.TryUseNativeMKL()) Console.WriteLine(Control.LinearAlgebraProvider);
if (Control.TryUseNativeCUDA()) Console.WriteLine(Control.LinearAlgebraProvider);
if (Control.TryUseNativeOpenBLAS()) Console.WriteLine(Control.LinearAlgebraProvider);
BenchmarkRunner.Run<FFT>();
//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");
}
}
}

0
src/Performance/Properties/AssemblyInfo.cs → src/Benchmark/Properties/AssemblyInfo.cs

2
src/Benchmark/paket.references

@ -0,0 +1,2 @@
group Benchmark
BenchmarkDotNet

1
src/Numerics/Numerics.csproj

@ -485,6 +485,5 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

557
src/Performance/LinearAlgebra/DenseMatrixProduct.cs

@ -1,557 +0,0 @@
using System;
using Binarysharp.Benchmark;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.Providers.LinearAlgebra;
using MathNet.Numerics.Providers.LinearAlgebra.Mkl;
using MathNet.Numerics.Threading;
namespace Performance.LinearAlgebra
{
public class DenseMatrixProduct
{
readonly int _rounds;
readonly Matrix<double> _a;
readonly Matrix<double> _b;
readonly ILinearAlgebraProvider _managed = new ManagedLinearAlgebraProvider();
readonly ILinearAlgebraProvider _mkl = new MklLinearAlgebraProvider();
readonly ILinearAlgebraProvider _safeProvider = new SafeProvider();
readonly ILinearAlgebraProvider _unsafeProvider = new UnsafeProvider();
readonly ILinearAlgebraProvider _experimentalProvider = new ExperimentalProvider();
public DenseMatrixProduct(int size, int rounds)
{
_rounds = rounds;
_b = Matrix<double>.Build.Random(size, size);
_a = Matrix<double>.Build.Random(size, size);
_managed.InitializeVerify();
_safeProvider.InitializeVerify();
_unsafeProvider.InitializeVerify();
_experimentalProvider.InitializeVerify();
#if NATIVE
_mkl.InitializeVerify();
#endif
}
public static void Verify(int size)
{
var x = new DenseMatrixProduct(size, 1);
var managedResult = x.ManagedProvider();
var mklResult = x.MklProvider();
var safeResult = x.SafeProvider();
var unsafeResult = x.UnsafeProvider();
var experimentalResult = x.ExperimentalProvider();
Console.WriteLine(managedResult.ToString());
//Console.WriteLine(mklResult.ToString());
//Console.WriteLine(safeResult.ToString());
//Console.WriteLine(unsafeResult.ToString());
//Console.WriteLine(experimentalResult.ToString());
if (!managedResult.AlmostEqual(mklResult, 1e-12))
{
throw new Exception("MklProvider");
}
if (!managedResult.AlmostEqual(safeResult, 1e-12))
{
throw new Exception("SafeProvider");
}
if (!managedResult.AlmostEqual(unsafeResult, 1e-12))
{
throw new Exception("UnsafeProvider");
}
if (!managedResult.AlmostEqual(experimentalResult, 1e-12))
{
throw new Exception("ExperimentalProvider");
}
}
[BenchSharkTask("ManagedProvider")]
public Matrix<double> ManagedProvider()
{
Control.LinearAlgebraProvider = _managed;
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a*z;
}
return z;
}
[BenchSharkTask("MklProvider")]
public Matrix<double> MklProvider()
{
Control.LinearAlgebraProvider = _mkl;
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a*z;
}
return z;
}
[BenchSharkTask("SafeProvider")]
public Matrix<double> SafeProvider()
{
Control.LinearAlgebraProvider = _safeProvider;
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a*z;
}
return z;
}
[BenchSharkTask("UnsafeProvider")]
public Matrix<double> UnsafeProvider()
{
Control.LinearAlgebraProvider = _unsafeProvider;
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a*z;
}
return z;
}
[BenchSharkTask("ExperimentalProvider")]
public Matrix<double> ExperimentalProvider()
{
Control.LinearAlgebraProvider = _experimentalProvider;
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a*z;
}
return z;
}
}
public class SafeProvider : ManagedLinearAlgebraProvider
{
public override void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
{
if (rowsX + columnsY <= Control.ParallelizeOrder)
{
for (int i = 0; i < rowsX; ++i)
{
for (int j = 0; j < columnsY; ++j)
{
var jrowsY = j*rowsY;
double sum = 0.0;
for (int k = 0; k < columnsX; ++k)
{
sum += x[k*rowsX + i]*y[jrowsY + k];
}
result[j*rowsX + i] = sum;
}
}
return;
}
double[] xdata;
if (ReferenceEquals(x, result))
{
xdata = (double[])x.Clone();
}
else
{
xdata = x;
}
double[] ydata;
if (ReferenceEquals(y, result))
{
ydata = (double[])y.Clone();
}
else
{
ydata = y;
}
Array.Clear(result, 0, result.Length);
CacheObliviousMatrixMultiply(xdata, 0, 0, ydata, 0, 0, result, 0, 0, rowsX, columnsY, columnsX, rowsX, columnsY, columnsX, 0);
}
public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
{
if (transposeA == Transpose.DontTranspose && transposeB == Transpose.DontTranspose && alpha == 1.0 && beta == 0.0)
{
MatrixMultiply(a, rowsA, columnsA, b, rowsB, columnsB, c);
return;
}
base.MatrixMultiplyWithUpdate(transposeA, transposeB, alpha, a, rowsA, columnsA, b, rowsB, columnsB, beta, c);
}
static void CacheObliviousMatrixMultiply(double[] matrixA, int shiftArow, int shiftAcol, double[] matrixB, int shiftBrow, int shiftBcol, double[] result, int shiftCrow, int shiftCcol, int m, int n, int k, int constM, int constN, int constK, int level)
{
if (m + n <= Control.ParallelizeOrder)
{
for (var m1 = 0; m1 < m; m1++)
{
var matArowPos = m1 + shiftArow;
var matCrowPos = m1 + shiftCrow;
for (var n1 = 0; n1 < n; ++n1)
{
var boffset = ((n1 + shiftBcol)*constK) + shiftBrow;
double sum = 0;
for (var k1 = 0; k1 < k; ++k1)
{
sum += matrixA[((k1 + shiftAcol)*constM) + matArowPos]*matrixB[boffset + k1];
}
result[((n1 + shiftCcol)*constM) + matCrowPos] += sum;
}
}
return;
}
// divide and conquer
int m2 = m/2, n2 = n/2, k2 = k/2;
level++;
if (level <= 2)
{
CommonParallel.Invoke(
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level));
CommonParallel.Invoke(
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level));
}
else
{
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level);
}
}
}
public unsafe class UnsafeProvider : ManagedLinearAlgebraProvider
{
public override void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
{
if (rowsX + columnsY <= Control.ParallelizeOrder)
{
fixed (double* resultPtr = &result[0])
fixed (double* xPtr = &x[0])
fixed (double* yPtr = &y[0])
{
double* a = xPtr;
double* c = resultPtr;
for (int i = 0; i < rowsX; ++i)
{
double* b = yPtr;
double* cj = c;
for (int j = 0; j < columnsY; ++j)
{
double sum = 0.0;
for (int k = 0; k < columnsX; ++k)
{
sum += a[k*rowsX]*b[k];
}
*cj = sum;
cj += rowsX;
b += rowsY;
}
a++;
c++;
}
}
return;
}
double[] xdata;
if (ReferenceEquals(x, result))
{
xdata = (double[])x.Clone();
}
else
{
xdata = x;
}
double[] ydata;
if (ReferenceEquals(y, result))
{
ydata = (double[])y.Clone();
}
else
{
ydata = y;
}
Array.Clear(result, 0, result.Length);
CacheObliviousMatrixMultiply(xdata, 0, 0, ydata, 0, 0, result, 0, 0, rowsX, columnsY, columnsX, rowsX, columnsY, columnsX, 0);
}
public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
{
if (transposeA == Transpose.DontTranspose && transposeB == Transpose.DontTranspose && alpha == 1.0 && beta == 0.0)
{
MatrixMultiply(a, rowsA, columnsA, b, rowsB, columnsB, c);
return;
}
base.MatrixMultiplyWithUpdate(transposeA, transposeB, alpha, a, rowsA, columnsA, b, rowsB, columnsB, beta, c);
}
static void CacheObliviousMatrixMultiply(double[] matrixA, int shiftArow, int shiftAcol, double[] matrixB, int shiftBrow, int shiftBcol, double[] result, int shiftCrow, int shiftCcol, int m, int n, int k, int constM, int constN, int constK, int level)
{
if (m + n <= Control.ParallelizeOrder)
{
fixed (double* resultPtr = &result[0])
fixed (double* aPtr = &matrixA[0])
fixed (double* bPtr = &matrixB[0])
{
double* a = aPtr + shiftArow;
double* c = resultPtr + shiftCrow;
for (var m1 = 0; m1 < m; m1++)
{
for (var n1 = 0; n1 < n; ++n1)
{
double* b = bPtr + (n1 + shiftBcol)*constK + shiftBrow;
double sum = 0;
for (var k1 = 0; k1 < k; ++k1)
{
sum += a[((k1 + shiftAcol)*constM)]*b[k1];
}
c[((n1 + shiftCcol)*constM)] += sum;
}
a++;
c++;
}
}
return;
}
// divide and conquer
int m2 = m/2, n2 = n/2, k2 = k/2;
level++;
if (level <= 2)
{
CommonParallel.Invoke(
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level));
CommonParallel.Invoke(
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level),
() => CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level));
}
else
{
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow, shiftCcol, m2, n2, k - k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow, shiftCcol + n2, m2, n - n2, k - k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol, matrixB, shiftBrow, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol, result, shiftCrow + m2, shiftCcol, m - m2, n2, k - k2, constM, constN, constK, level);
CacheObliviousMatrixMultiply(matrixA, shiftArow + m2, shiftAcol + k2, matrixB, shiftBrow + k2, shiftBcol + n2, result, shiftCrow + m2, shiftCcol + n2, m - m2, n - n2, k - k2, constM, constN, constK, level);
}
}
}
public class ExperimentalProvider : ManagedLinearAlgebraProvider
{
public override void MatrixMultiply(double[] x, int rowsX, int columnsX, double[] y, int rowsY, int columnsY, double[] result)
{
MatrixMultiplyWithUpdate(Transpose.DontTranspose, Transpose.DontTranspose, 1.0, x, rowsX, columnsX, y, rowsY, columnsY, 0.0, result);
}
public override void MatrixMultiplyWithUpdate(Transpose transposeA, Transpose transposeB, double alpha, double[] a, int rowsA, int columnsA, double[] b, int rowsB, int columnsB, double beta, double[] c)
{
if (a == null)
{
throw new ArgumentNullException("a");
}
if (b == null)
{
throw new ArgumentNullException("b");
}
if (c == null)
{
throw new ArgumentNullException("c");
}
if (transposeA != Transpose.DontTranspose)
{
Swap(ref rowsA, ref columnsA);
}
if (transposeB != Transpose.DontTranspose)
{
Swap(ref rowsB, ref columnsB);
}
if (columnsA != rowsB)
{
throw new ArgumentOutOfRangeException(String.Format("columnsA ({0}) != rowsB ({1})", columnsA, rowsB));
}
if (rowsA*columnsA != a.Length)
{
throw new ArgumentOutOfRangeException(String.Format("rowsA ({0}) * columnsA ({1}) != a.Length ({2})", rowsA, columnsA, a.Length));
}
if (rowsB*columnsB != b.Length)
{
throw new ArgumentOutOfRangeException(String.Format("rowsB ({0}) * columnsB ({1}) != b.Length ({2})", rowsB, columnsB, b.Length));
}
if (rowsA*columnsB != c.Length)
{
throw new ArgumentOutOfRangeException(String.Format("rowsA ({0}) * columnsB ({1}) != c.Length ({2})", rowsA, columnsB, c.Length));
}
// handle the degenerate cases
if (beta == 0.0)
{
Array.Clear(c, 0, c.Length);
}
else if (beta != 1.0)
{
ScaleArray(beta, c, c);
}
if (alpha == 0.0)
{
return;
}
// Extract column arrays
var columnDataB = new double[columnsB][];
for (int i = 0; i < columnDataB.Length; i++)
{
columnDataB[i] = GetColumn(transposeB, i, rowsB, columnsB, b);
}
var shouldNotParallelize = rowsA + columnsB + columnsA < Control.ParallelizeOrder || Control.MaxDegreeOfParallelism < 2;
if (shouldNotParallelize)
{
for (int i = 0; i < rowsA; i++)
{
var row = GetRow(transposeA, i, rowsA, columnsA, a);
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];
}
c[j*rowsA + i] += alpha*sum;
}
}
}
else
{
CommonParallel.For(0, rowsA, 1, (u, v) =>
{
for (int i = u; i < v; i++)
{
// for each row in a
var row = GetRow(transposeA, i, rowsA, columnsA, a);
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];
}
c[j*rowsA + i] += alpha*sum;
}
}
});
}
}
static void Swap(ref int first, ref int second)
{
var prior = first;
first = second;
second = prior;
}
/// <summary>
/// Assumes that <paramref name="numRows"/> and <paramref name="numCols"/> have already been transposed.
/// </summary>
static double[] GetRow(Transpose transpose, int rowindx, int numRows, int numCols, double[] matrix)
{
var ret = new double[numCols];
if (transpose == Transpose.DontTranspose)
{
for (int i = 0; i < numCols; i++)
{
ret[i] = matrix[(i*numRows) + rowindx];
}
}
else
{
Array.Copy(matrix, rowindx*numCols, ret, 0, numCols);
}
return ret;
}
/// <summary>
/// Assumes that <paramref name="numRows"/> and <paramref name="numCols"/> have already been transposed.
/// </summary>
static double[] GetColumn(Transpose transpose, int colindx, int numRows, int numCols, double[] matrix)
{
var ret = new double[numRows];
if (transpose == Transpose.DontTranspose)
{
Array.Copy(matrix, colindx*numRows, ret, 0, numRows);
}
else
{
for (int i = 0; i < numRows; i++)
{
ret[i] = matrix[(i*numCols) + colindx];
}
}
return ret;
}
}
}

150
src/Performance/LinearAlgebra/DenseVectorAdd.cs

@ -1,150 +0,0 @@
using System;
using Binarysharp.Benchmark;
using MathNet.Numerics;
using MathNet.Numerics.Providers.LinearAlgebra;
using MathNet.Numerics.Providers.LinearAlgebra.Mkl;
using MathNet.Numerics.Threading;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Storage;
namespace Performance.LinearAlgebra
{
public class DenseVectorAdd
{
readonly int _rounds;
readonly Vector<double> _a;
readonly Vector<double> _b;
readonly ILinearAlgebraProvider _managed = new ManagedLinearAlgebraProvider();
readonly ILinearAlgebraProvider _mkl = new MklLinearAlgebraProvider();
public DenseVectorAdd(int size, int rounds)
{
_rounds = rounds;
_b = Vector<double>.Build.Random(size);
_a = Vector<double>.Build.Random(size);
_managed.InitializeVerify();
Control.LinearAlgebraProvider = _managed;
#if NATIVE
_mkl.InitializeVerify();
#endif
}
[BenchSharkTask("AddOperator")]
public Vector<double> AddOperator()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a + z;
}
return z;
}
[BenchSharkTask("Map2")]
public Vector<double> Map2()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
z = _a.Map2((u, v) => u + v, z);
}
return z;
}
[BenchSharkTask("Loop")]
public Vector<double> Loop()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
var az = ((DenseVectorStorage<double>)z.Storage).Data;
var ar = new Double[aa.Length];
for (int k = 0; k < ar.Length; k++)
{
ar[k] = aa[k] + az[k];
}
z = Vector<double>.Build.Dense(ar);
}
return z;
}
[BenchSharkTask("ParallelLoop4096")]
public Vector<double> ParallelLoop4096()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
var az = ((DenseVectorStorage<double>)z.Storage).Data;
var ar = new Double[aa.Length];
CommonParallel.For(0, ar.Length, 4096, (u, v) =>
{
for (int k = u; k < v; k++)
{
ar[k] = aa[k] + az[k];
}
});
z = Vector<double>.Build.Dense(ar);
}
return z;
}
[BenchSharkTask("ParallelLoop32768")]
public Vector<double> ParallelLoop32768()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
var az = ((DenseVectorStorage<double>)z.Storage).Data;
var ar = new Double[aa.Length];
CommonParallel.For(0, ar.Length, 32768, (u, v) =>
{
for (int k = u; k < v; k++)
{
ar[k] = aa[k] + az[k];
}
});
z = Vector<double>.Build.Dense(ar);
}
return z;
}
[BenchSharkTask("ManagedProvider")]
public Vector<double> ManagedProvider()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
var az = ((DenseVectorStorage<double>)z.Storage).Data;
var ar = new Double[aa.Length];
_managed.AddArrays(aa, az, ar);
z = Vector<double>.Build.Dense(ar);
}
return z;
}
#if NATIVEMKL
[BenchSharkTask("MklProvider")]
public Vector<double> MklProvider()
{
var z = _b;
for (int i = 0; i < _rounds; i++)
{
var aa = ((DenseVectorStorage<double>)_a.Storage).Data;
var az = ((DenseVectorStorage<double>)z.Storage).Data;
var ar = new Double[aa.Length];
_mkl.AddArrays(aa, az, ar);
z = Vector<double>.Build.Dense(ar);
}
return z;
}
#endif
}
}

109
src/Performance/Performance.csproj

@ -1,109 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F2CA84AE-4B7C-46F5-9889-82BC5F9F0F4E}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Performance</RootNamespace>
<AssemblyName>Performance</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NATIVE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release %28No MKL%29|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="LinearAlgebra\DenseVectorAdd.cs" />
<Compile Include="LinearAlgebra\DenseMatrixProduct.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="paket.references" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Numerics\Numerics.csproj">
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project>
<Name>Numerics</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="..\..\out\MKL\Windows\x64\libiomp5md.dll">
<Link>libiomp5md.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="..\..\out\MKL\Windows\x64\MathNet.Numerics.MKL.dll">
<Link>MathNet.Numerics.MKL.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<Reference Include="Benchmark">
<HintPath>..\..\packages\benchmark\BenchShark\lib\Benchmark.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')">
<ItemGroup>
<Reference Include="ConsoleDump">
<HintPath>..\..\packages\benchmark\ConsoleDump\lib\net40-Client\ConsoleDump.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
</Project>

52
src/Performance/Program.cs

@ -1,52 +0,0 @@
using System;
using System.Linq;
using Binarysharp.Benchmark;
using ConsoleDump;
using MathNet.Numerics.Statistics;
namespace Performance
{
public class Program
{
public static void Main()
{
//Benchmark(new LinearAlgebra.DenseVectorAdd(10000000,1), 10, "Large (10'000'000) - 10x1 iterations");
//Benchmark(new LinearAlgebra.DenseVectorAdd(100,1000), 100, "Small (100) - 100x1000 iterations");
LinearAlgebra.DenseMatrixProduct.Verify(5);
LinearAlgebra.DenseMatrixProduct.Verify(100);
Benchmark(new LinearAlgebra.DenseMatrixProduct(10,100), 100, "10 - 100x100 iterations");
Benchmark(new LinearAlgebra.DenseMatrixProduct(25, 100), 100, "25 - 100x100 iterations");
Benchmark(new LinearAlgebra.DenseMatrixProduct(50, 10), 100, "50 - 100x10 iterations");
Benchmark(new LinearAlgebra.DenseMatrixProduct(100, 10), 100, "100 - 100x10 iterations");
Benchmark(new LinearAlgebra.DenseMatrixProduct(250, 1), 10, "250 - 10x1 iterations");
Benchmark(new LinearAlgebra.DenseMatrixProduct(500,1), 10, "500 - 10x1 iterations");
Benchmark(new LinearAlgebra.DenseMatrixProduct(1000,1), 2, "1000 - 2x1 iterations");
}
static void Benchmark(object obj, uint iterations, string suffix = null)
{
var bench = new BenchShark(true);
var result = bench.EvaluateDecoratedTasks(obj, iterations);
var results = result.FastestEvaluations.Select(x =>
{
var series = x.Iterations.Select(it => (double)it.ElapsedTicks).ToArray();
Array.Sort(series);
var summary = SortedArrayStatistics.FiveNumberSummary(series);
var ms = ArrayStatistics.MeanStandardDeviation(series);
return new { x.Name, Mean = ms.Item1, StdDev = ms.Item2, Min = summary[0], Q1 = summary[1], Median = summary[2], Q3 = summary[3], Max = summary[4] };
}).ToArray();
var top = results[0];
var managed = results.Single(x => x.Name.StartsWith("Managed"));
var label = string.IsNullOrEmpty(suffix) ? obj.GetType().FullName : string.Concat(obj.GetType().FullName, ": ", suffix);
results.Select(x => new
{
x.Name,
Mean = Math.Round(x.Mean), StdDev = Math.Round(x.StdDev),
Min = Math.Round(x.Min), Q1 = Math.Round(x.Q1), Median = Math.Round(x.Median), Q3 = Math.Round(x.Q3), Max = Math.Round(x.Max),
TopSlowdown = Math.Round(x.Median/top.Median, 2),
ManagedSpeedup = Math.Round(managed.Median/x.Median, 2)
}).Dump(label);
}
}
}

3
src/Performance/paket.references

@ -1,3 +0,0 @@
group Benchmark
BenchShark
ConsoleDump
Loading…
Cancel
Save