diff --git a/src/NativeProviders/MKL/capabilities.cpp b/src/NativeProviders/MKL/capabilities.cpp index 21502a82..159d38c3 100644 --- a/src/NativeProviders/MKL/capabilities.cpp +++ b/src/NativeProviders/MKL/capabilities.cpp @@ -1,4 +1,5 @@ #include "wrapper_common.h" +#include "mkl.h" #ifdef __cplusplus extern "C" { @@ -40,7 +41,8 @@ extern "C" { #endif // COMMON/SHARED - case 64: return 4; // revision + case 64: return 5; // revision + case 65: return 1; // numerical consistency, precision and accuracy modes // LINEAR ALGEBRA case 128: return 1; // basic dense linear algebra @@ -56,6 +58,24 @@ extern "C" { } } + DLLEXPORT void set_consistency_mode(const MKL_INT mode) + { + mkl_cbwr_set(mode); + } + + DLLEXPORT void set_vml_mode(const MKL_UINT mode) + { + vmlSetMode(mode); + } + + /* Obsolete, will be dropped in the next revision */ + DLLEXPORT void SetImprovedConsistency(void) + { + // set improved consistency for MKL and vector functions + mkl_cbwr_set(MKL_CBWR_COMPATIBLE); + vmlSetMode(VML_HA | VML_DOUBLE_CONSISTENT); + } + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/NativeProviders/MKL/lapack.cpp b/src/NativeProviders/MKL/lapack.cpp index 1ae473c2..1ad5a353 100644 --- a/src/NativeProviders/MKL/lapack.cpp +++ b/src/NativeProviders/MKL/lapack.cpp @@ -750,11 +750,4 @@ extern "C" { return eigen_complex_factor(n, a, vectors, values, d, LAPACKE_zgees, LAPACKE_ztrevc); } } - - DLLEXPORT void SetImprovedConsistency(void) - { - // set improved consistency for mkl and vector functions - mkl_cbwr_set(MKL_CBWR_COMPATIBLE); - vmlSetMode(VML_HA|VML_DOUBLE_CONSISTENT); - } -} \ No newline at end of file +} diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs index dcff254d..8cc065a4 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2013 Math.NET +// Copyright (c) 2009-2014 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -34,6 +34,39 @@ using System; namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl { + /// + /// Consistency vs. performance trade-off between runs on different machines. + /// + public enum MklConsistency : int + { + /// Consistent on the same CPU only (maximum performance) + Auto = 2, + /// Consistent on Intel and compatible CPUs with SSE2 support (maximum compatibility) + Compatible = 3, + /// Consistent on Intel CPUs supporting SSE2 or later + SSE2 = 4, + /// Consistent on Intel CPUs supporting SSE4.2 or later + SSE4_2 = 8, + /// Consistent on Intel CPUs supporting AVX or later + AVX = 9, + /// Consistent on Intel CPUs supporting AVX2 or later + AVX2 = 10 + } + + [CLSCompliant(false)] + public enum MklAccuracy : uint + { + Low = 0x1, + High = 0x2 + } + + [CLSCompliant(false)] + public enum MklPrecision : uint + { + Single = 0x10, + Double = 0x20 + } + /// /// Intel's Math Kernel Library (MKL) linear algebra provider. /// @@ -44,17 +77,37 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl bool _nativeX64 = false; bool _nativeIA64 = false; - /// If true improves MKL Consistency to get bit consistent results on repeated identical calculations - public MklLinearAlgebraProvider(bool bitConsistent = false) + readonly MklConsistency _consistency; + readonly MklPrecision _precision; + readonly MklAccuracy _accuracy; + + /// + /// Sets the desired bit consistency on repeated identical computations on varying CPU architectures, + /// as a trade-off with performance. + /// + /// VML optimal precision and rounding. + /// VML accuracy mode. + [CLSCompliant(false)] + public MklLinearAlgebraProvider( + MklConsistency consistency = MklConsistency.Auto, + MklPrecision precision = MklPrecision.Double, + MklAccuracy accuracy = MklAccuracy.High) { - if (bitConsistent) - { - SafeNativeMethods.SetImprovedConsistency(); - } + _consistency = consistency; + _precision = precision; + _accuracy = accuracy; + } + + public MklLinearAlgebraProvider() + { + _consistency = MklConsistency.Auto; + _precision = MklPrecision.Double; + _accuracy = MklAccuracy.High; } /// - /// Initialize and verify that the provided is indeed available. If not, fall back to alernatives like the managed provider + /// Initialize and verify that the provided is indeed available. + /// If calling this method fails, consider to fall back to alternatives like the managed provider. /// public override void InitializeVerify() { @@ -91,6 +144,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl { throw new NotSupportedException("MKL Native Provider too old or not compatible (2)."); } + + if (SafeNativeMethods.query_capability(65) > 0) + { + SafeNativeMethods.set_consistency_mode((int)_consistency); + SafeNativeMethods.set_vml_mode((uint)_precision | (uint)_accuracy); + } } public override string ToString() diff --git a/src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs b/src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs index b6dfc59d..02f9531f 100644 --- a/src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs +++ b/src/Numerics/Providers/LinearAlgebra/Mkl/SafeNativeMethods.cs @@ -49,6 +49,12 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern int query_capability(int capability); + [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern void set_consistency_mode(int mode); + + [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] + internal static extern void set_vml_mode(uint mode); + #region BLAS [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] @@ -103,9 +109,6 @@ namespace MathNet.Numerics.Providers.LinearAlgebra.Mkl #region LAPACK - [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] - internal static extern void SetImprovedConsistency(); - [DllImport(DllName, ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)] internal static extern float s_matrix_norm(byte norm, int rows, int columns, [In] float[] a, [In, Out] float[] work);