Browse Source

FFT: MKL provider refactoring due to sharing between FFT and LA - 2

pull/445/head
Christoph Ruegg 10 years ago
parent
commit
d7440d5125
  1. 15
      src/Numerics/Control.cs
  2. 1
      src/Numerics/Numerics.csproj
  3. 139
      src/Numerics/Providers/Common/Mkl/MklProvider.cs
  4. 2
      src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs
  5. 66
      src/Numerics/Providers/Common/Mkl/MklProviderPrecision.cs
  6. 60
      src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs
  7. 12
      src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs
  8. 119
      src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs

15
src/Numerics/Control.cs

@ -135,6 +135,7 @@ namespace MathNet.Numerics
/// Throws if it is not available or failed to initialize, in which case the previous provider is still active.
/// </summary>
[CLSCompliant(false)]
[Obsolete("Will be removed in the next major version. Use the enums in the Common namespace instead.")]
public static void UseNativeMKL(
Providers.LinearAlgebra.Mkl.MklConsistency consistency = Providers.LinearAlgebra.Mkl.MklConsistency.Auto,
Providers.LinearAlgebra.Mkl.MklPrecision precision = Providers.LinearAlgebra.Mkl.MklPrecision.Double,
@ -144,6 +145,20 @@ namespace MathNet.Numerics
FourierTransformProvider = new Providers.FourierTransform.Mkl.MklFourierTransformProvider();
}
/// <summary>
/// Use the Intel MKL native provider for linear algebra, with the specified configuration parameters.
/// Throws if it is not available or failed to initialize, in which case the previous provider is still active.
/// </summary>
[CLSCompliant(false)]
public static void UseNativeMKL(
Providers.Common.Mkl.MklConsistency consistency = Providers.Common.Mkl.MklConsistency.Auto,
Providers.Common.Mkl.MklPrecision precision = Providers.Common.Mkl.MklPrecision.Double,
Providers.Common.Mkl.MklAccuracy accuracy = Providers.Common.Mkl.MklAccuracy.High)
{
LinearAlgebraProvider = new Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider(consistency, precision, accuracy);
FourierTransformProvider = new Providers.FourierTransform.Mkl.MklFourierTransformProvider();
}
/// <summary>
/// Try to use the Intel MKL native provider for linear algebra.
/// </summary>

1
src/Numerics/Numerics.csproj

@ -173,6 +173,7 @@
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Providers\Common\Mkl\MklProvider.cs" />
<Compile Include="Providers\Common\Mkl\MklProviderPrecision.cs" />
<Compile Include="Providers\FourierTransform\IFourierTransformProvider.cs" />
<Compile Include="Providers\FourierTransform\ManagedFourierTransformProvider.cs" />
<Compile Include="Providers\FourierTransform\Mkl\MklFourierTransformProvider.cs" />

139
src/Numerics/Providers/Common/Mkl/MklProvider.cs

@ -72,6 +72,122 @@ namespace MathNet.Numerics.Providers.Common.Mkl
{
throw new NotSupportedException("MKL Native Provider too old. Consider upgrading to a newer version.");
}
ConfigureThreading();
}
static void ConfigureThreading()
{
// set threading settings, if supported
if (SafeNativeMethods.query_capability((int)ProviderConfig.Threading) > 0)
{
SafeNativeMethods.set_max_threads(Control.MaxDegreeOfParallelism);
}
}
public static void ConfigurePrecision(MklConsistency consistency, MklPrecision precision, MklAccuracy accuracy)
{
// set numerical consistency, precision and accuracy modes, if supported
if (SafeNativeMethods.query_capability((int)ProviderConfig.Precision) > 0)
{
SafeNativeMethods.set_consistency_mode((int)consistency);
SafeNativeMethods.set_vml_mode((uint)precision | (uint)accuracy);
}
}
/// <summary>
/// Frees the memory allocated to the MKL memory pool.
/// </summary>
public static void FreeBuffers()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.free_buffers();
}
/// <summary>
/// Frees the memory allocated to the MKL memory pool on the current thread.
/// </summary>
public static void ThreadFreeBuffers()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.thread_free_buffers();
}
/// <summary>
/// Disable the MKL memory pool. May impact performance.
/// </summary>
public static void DisableMemoryPool()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.disable_fast_mm();
}
/// <summary>
/// Retrieves information about the MKL memory pool.
/// </summary>
/// <param name="allocatedBuffers">On output, returns the number of memory buffers allocated.</param>
/// <returns>Returns the number of bytes allocated to all memory buffers.</returns>
public static long MemoryStatistics(out int allocatedBuffers)
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
return SafeNativeMethods.mem_stat(out allocatedBuffers);
}
/// <summary>
/// Enable gathering of peak memory statistics of the MKL memory pool.
/// </summary>
public static void EnablePeakMemoryStatistics()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.peak_mem_usage((int)MklMemoryRequestMode.Enable);
}
/// <summary>
/// Disable gathering of peak memory statistics of the MKL memory pool.
/// </summary>
public static void DisablePeakMemoryStatistics()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.peak_mem_usage((int)MklMemoryRequestMode.Disable);
}
/// <summary>
/// Measures peak memory usage of the MKL memory pool.
/// </summary>
/// <param name="reset">Whether the usage counter should be reset.</param>
/// <returns>The peak number of bytes allocated to all memory buffers.</returns>
public static long PeakMemoryStatistics(bool reset = true)
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
return SafeNativeMethods.peak_mem_usage((int)(reset ? MklMemoryRequestMode.PeakMemoryReset : MklMemoryRequestMode.PeakMemory));
}
public static string Describe()
@ -80,5 +196,28 @@ namespace MathNet.Numerics.Providers.Common.Mkl
_nativeRevision,
_nativeX86 ? "x86" : _nativeX64 ? "x64" : _nativeIA64 ? "IA64" : "unknown");
}
enum MklMemoryRequestMode : int
{
/// <summary>
/// Disable gathering memory usage
/// </summary>
Disable = 0,
/// <summary>
/// Enable gathering memory usage
/// </summary>
Enable = 1,
/// <summary>
/// Return peak memory usage
/// </summary>
PeakMemory = 2,
/// <summary>
/// Return peak memory usage and reset counter
/// </summary>
PeakMemoryReset = -1
}
}
}

2
src/Numerics/Providers/Common/Mkl/MklProviderCapabilities.cs

@ -3,7 +3,7 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2015 Math.NET
// Copyright (c) 2009-2016 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

66
src/Numerics/Providers/Common/Mkl/MklProviderPrecision.cs

@ -0,0 +1,66 @@
// <copyright file="MklProviderPrecision.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2016 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
namespace MathNet.Numerics.Providers.Common.Mkl
{
/// <summary>
/// Consistency vs. performance trade-off between runs on different machines.
/// </summary>
public enum MklConsistency : int
{
/// <summary>Consistent on the same CPU only (maximum performance)</summary>
Auto = 2,
/// <summary>Consistent on Intel and compatible CPUs with SSE2 support (maximum compatibility)</summary>
Compatible = 3,
/// <summary>Consistent on Intel CPUs supporting SSE2 or later</summary>
SSE2 = 4,
/// <summary>Consistent on Intel CPUs supporting SSE4.2 or later</summary>
SSE4_2 = 8,
/// <summary>Consistent on Intel CPUs supporting AVX or later</summary>
AVX = 9,
/// <summary>Consistent on Intel CPUs supporting AVX2 or later</summary>
AVX2 = 10
}
[CLSCompliant(false)]
public enum MklAccuracy : uint
{
Low = 0x1,
High = 0x2
}
[CLSCompliant(false)]
public enum MklPrecision : uint
{
Single = 0x10,
Double = 0x20
}
}

60
src/Numerics/Providers/FourierTransform/Mkl/MklFourierTransformProvider.cs

@ -49,6 +49,66 @@ namespace MathNet.Numerics.Providers.FourierTransform.Mkl
}
}
/// <summary>
/// Frees the memory allocated to the MKL memory pool.
/// </summary>
public void FreeBuffers()
{
MklProvider.FreeBuffers();
}
/// <summary>
/// Frees the memory allocated to the MKL memory pool on the current thread.
/// </summary>
public void ThreadFreeBuffers()
{
MklProvider.ThreadFreeBuffers();
}
/// <summary>
/// Disable the MKL memory pool. May impact performance.
/// </summary>
public void DisableMemoryPool()
{
MklProvider.DisableMemoryPool();
}
/// <summary>
/// Retrieves information about the MKL memory pool.
/// </summary>
/// <param name="allocatedBuffers">On output, returns the number of memory buffers allocated.</param>
/// <returns>Returns the number of bytes allocated to all memory buffers.</returns>
public long MemoryStatistics(out int allocatedBuffers)
{
return MklProvider.MemoryStatistics(out allocatedBuffers);
}
/// <summary>
/// Enable gathering of peak memory statistics of the MKL memory pool.
/// </summary>
public void EnablePeakMemoryStatistics()
{
MklProvider.EnablePeakMemoryStatistics();
}
/// <summary>
/// Disable gathering of peak memory statistics of the MKL memory pool.
/// </summary>
public void DisablePeakMemoryStatistics()
{
MklProvider.DisablePeakMemoryStatistics();
}
/// <summary>
/// Measures peak memory usage of the MKL memory pool.
/// </summary>
/// <param name="reset">Whether the usage counter should be reset.</param>
/// <returns>The peak number of bytes allocated to all memory buffers.</returns>
public long PeakMemoryStatistics(bool reset = true)
{
return MklProvider.PeakMemoryStatistics(reset);
}
public override string ToString()
{
return MklProvider.Describe();

12
src/Numerics/Providers/LinearAlgebra/ILinearAlgebraProvider.cs

@ -2,9 +2,9 @@
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
//
// Copyright (c) 2009-2013 Math.NET
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -13,10 +13,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -151,7 +151,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
T DotProduct(T[] x, T[] y);
/// <summary>
/// Does a point wise add of two arrays <c>z = x + y</c>. This can be used
/// Does a point wise add of two arrays <c>z = x + y</c>. This can be used
/// to add vectors or matrices.
/// </summary>
/// <param name="x">The array x.</param>
@ -163,7 +163,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra
void AddArrays(T[] x, T[] y, T[] result);
/// <summary>
/// Does a point wise subtraction of two arrays <c>z = x - y</c>. This can be used
/// Does a point wise subtraction of two arrays <c>z = x - y</c>. This can be used
/// to subtract vectors or matrices.
/// </summary>
/// <param name="x">The array x.</param>

119
src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs

@ -49,6 +49,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <summary>
/// Consistency vs. performance trade-off between runs on different machines.
/// </summary>
[Obsolete("Will be removed in the next major version. Use the enums in the Common namespace instead.")]
public enum MklConsistency : int
{
/// <summary>Consistent on the same CPU only (maximum performance)</summary>
@ -66,6 +67,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
}
[CLSCompliant(false)]
[Obsolete("Will be removed in the next major version. Use the enums in the Common namespace instead.")]
public enum MklAccuracy : uint
{
Low = 0x1,
@ -73,43 +75,21 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
}
[CLSCompliant(false)]
[Obsolete("Will be removed in the next major version. Use the enums in the Common namespace instead.")]
public enum MklPrecision : uint
{
Single = 0x10,
Double = 0x20
}
internal enum MklMemoryRequestMode : int
{
/// <summary>
/// Disable gathering memory usage
/// </summary>
Disable = 0,
/// <summary>
/// Enable gathering memory usage
/// </summary>
Enable = 1,
/// <summary>
/// Return peak memory usage
/// </summary>
PeakMemory = 2,
/// <summary>
/// Return peak memory usage and reset counter
/// </summary>
PeakMemoryReset = -1
}
/// <summary>
/// Intel's Math Kernel Library (MKL) linear algebra provider.
/// </summary>
public partial class MklLinearAlgebraProvider : ManagedLinearAlgebraProvider
{
readonly MklConsistency _consistency;
readonly MklPrecision _precision;
readonly MklAccuracy _accuracy;
readonly Common.Mkl.MklConsistency _consistency;
readonly Common.Mkl.MklPrecision _precision;
readonly Common.Mkl.MklAccuracy _accuracy;
/// <param name="consistency">
/// Sets the desired bit consistency on repeated identical computations on varying CPU architectures,
@ -118,10 +98,28 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <param name="precision">VML optimal precision and rounding.</param>
/// <param name="accuracy">VML accuracy mode.</param>
[CLSCompliant(false)]
[Obsolete("Will be removed in the next major version. Use the enums in the Common namespace instead.")]
public MklLinearAlgebraProvider(
MklConsistency consistency = MklConsistency.Auto,
MklPrecision precision = MklPrecision.Double,
MklAccuracy accuracy = MklAccuracy.High)
{
_consistency = (Common.Mkl.MklConsistency)consistency;
_precision = (Common.Mkl.MklPrecision)precision;
_accuracy = (Common.Mkl.MklAccuracy)accuracy;
}
/// <param name="consistency">
/// Sets the desired bit consistency on repeated identical computations on varying CPU architectures,
/// as a trade-off with performance.
/// </param>
/// <param name="precision">VML optimal precision and rounding.</param>
/// <param name="accuracy">VML accuracy mode.</param>
[CLSCompliant(false)]
public MklLinearAlgebraProvider(
Common.Mkl.MklConsistency consistency = Common.Mkl.MklConsistency.Auto,
Common.Mkl.MklPrecision precision = Common.Mkl.MklPrecision.Double,
Common.Mkl.MklAccuracy accuracy = Common.Mkl.MklAccuracy.High)
{
_consistency = consistency;
_precision = precision;
@ -130,9 +128,9 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
public MklLinearAlgebraProvider()
{
_consistency = MklConsistency.Auto;
_precision = MklPrecision.Double;
_accuracy = MklAccuracy.High;
_consistency = Common.Mkl.MklConsistency.Auto;
_precision = Common.Mkl.MklPrecision.Double;
_accuracy = Common.Mkl.MklAccuracy.High;
}
/// <summary>
@ -142,6 +140,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
public override void InitializeVerify()
{
MklProvider.Load(minRevision: 4);
MklProvider.ConfigurePrecision(_consistency, _precision, _accuracy);
int linearAlgebra = SafeNativeMethods.query_capability((int)ProviderCapability.LinearAlgebraMajor);
@ -150,19 +149,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
{
throw new NotSupportedException(string.Format("MKL Native Provider not compatible. Expecting linear algebra v2 but provider implements v{0}.", linearAlgebra));
}
// set numerical consistency, precision and accuracy modes, if supported
if (SafeNativeMethods.query_capability((int)ProviderConfig.Precision) > 0)
{
SafeNativeMethods.set_consistency_mode((int)_consistency);
SafeNativeMethods.set_vml_mode((uint)_precision | (uint)_accuracy);
}
// set threading settings, if supported
if (SafeNativeMethods.query_capability((int)ProviderConfig.Threading) > 0)
{
SafeNativeMethods.set_max_threads(Control.MaxDegreeOfParallelism);
}
}
/// <summary>
@ -170,12 +156,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// </summary>
public void FreeBuffers()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.free_buffers();
MklProvider.FreeBuffers();
}
/// <summary>
@ -183,12 +164,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// </summary>
public void ThreadFreeBuffers()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.thread_free_buffers();
MklProvider.ThreadFreeBuffers();
}
/// <summary>
@ -196,12 +172,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// </summary>
public void DisableMemoryPool()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.disable_fast_mm();
MklProvider.DisableMemoryPool();
}
/// <summary>
@ -211,12 +182,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <returns>Returns the number of bytes allocated to all memory buffers.</returns>
public long MemoryStatistics(out int allocatedBuffers)
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
return SafeNativeMethods.mem_stat(out allocatedBuffers);
return MklProvider.MemoryStatistics(out allocatedBuffers);
}
/// <summary>
@ -224,12 +190,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// </summary>
public void EnablePeakMemoryStatistics()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.peak_mem_usage((int)MklMemoryRequestMode.Enable);
MklProvider.EnablePeakMemoryStatistics();
}
/// <summary>
@ -237,12 +198,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// </summary>
public void DisablePeakMemoryStatistics()
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
SafeNativeMethods.peak_mem_usage((int)MklMemoryRequestMode.Disable);
MklProvider.DisablePeakMemoryStatistics();
}
/// <summary>
@ -252,12 +208,7 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl
/// <returns>The peak number of bytes allocated to all memory buffers.</returns>
public long PeakMemoryStatistics(bool reset = true)
{
if (SafeNativeMethods.query_capability((int)ProviderConfig.Memory) < 1)
{
throw new NotSupportedException("MKL Native Provider does not support memory management functions. Consider upgrading to a newer version.");
}
return SafeNativeMethods.peak_mem_usage((int)(reset ? MklMemoryRequestMode.PeakMemoryReset : MklMemoryRequestMode.PeakMemory));
return MklProvider.PeakMemoryStatistics(reset);
}
public override string ToString()

Loading…
Cancel
Save