forked from tsai/mathnet-numerics
48 changed files with 1742 additions and 336 deletions
@ -0,0 +1,54 @@ |
|||||
|
#include "wrapper_common.h" |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
#include <float.h> |
||||
|
#include "mkl_dfti.h" |
||||
|
|
||||
|
template<typename Data, typename Precision, typename FFT> |
||||
|
inline MKL_INT64 fft_1d_inplace(const MKL_INT64 n, Data x[], const Precision forward_scale, const Precision backward_scale, const DFTI_CONFIG_VALUE precision, const DFTI_CONFIG_VALUE domain, FFT fft) |
||||
|
{ |
||||
|
MKL_LONG status; |
||||
|
DFTI_DESCRIPTOR_HANDLE descriptor = nullptr; |
||||
|
status = DftiCreateDescriptor(&descriptor, precision, domain, 1, static_cast<MKL_LONG>(n)); |
||||
|
if (0 != status) goto cleanup; |
||||
|
|
||||
|
status = DftiSetValue(descriptor, DFTI_FORWARD_SCALE, forward_scale); |
||||
|
if (0 != status) goto cleanup; |
||||
|
|
||||
|
status = DftiSetValue(descriptor, DFTI_BACKWARD_SCALE, backward_scale); |
||||
|
if (0 != status) goto cleanup; |
||||
|
|
||||
|
status = DftiCommitDescriptor(descriptor); |
||||
|
if (0 != status) goto cleanup; |
||||
|
|
||||
|
status = fft(descriptor, x); |
||||
|
|
||||
|
cleanup: |
||||
|
DftiFreeDescriptor(&descriptor); |
||||
|
return static_cast<MKL_INT64>(status); |
||||
|
} |
||||
|
|
||||
|
extern "C" { |
||||
|
|
||||
|
DLLEXPORT MKL_INT64 z_fft_forward_inplace(const MKL_INT64 n, const double scaling, MKL_Complex16 x[]) |
||||
|
{ |
||||
|
return fft_1d_inplace(n, x, scaling, 1.0, DFTI_DOUBLE, DFTI_COMPLEX, DftiComputeForward); |
||||
|
} |
||||
|
|
||||
|
DLLEXPORT MKL_INT64 c_fft_forward_inplace(const MKL_INT64 n, const float scaling, MKL_Complex8 x[]) |
||||
|
{ |
||||
|
return fft_1d_inplace(n, x, scaling, 1.0f, DFTI_SINGLE, DFTI_COMPLEX, DftiComputeForward); |
||||
|
} |
||||
|
|
||||
|
DLLEXPORT MKL_INT64 z_fft_backward_inplace(const MKL_INT64 n, const double scaling, MKL_Complex16 x[]) |
||||
|
{ |
||||
|
return fft_1d_inplace(n, x, 1.0, scaling, DFTI_DOUBLE, DFTI_COMPLEX, DftiComputeBackward); |
||||
|
} |
||||
|
|
||||
|
DLLEXPORT MKL_INT64 c_fft_backward_inplace(const MKL_INT64 n, const float scaling, MKL_Complex8 x[]) |
||||
|
{ |
||||
|
return fft_1d_inplace(n, x, 1.0f, scaling, DFTI_SINGLE, DFTI_COMPLEX, DftiComputeBackward); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
// <copyright file="CudaProvider.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>
|
||||
|
|
||||
|
#if NATIVE
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace MathNet.Numerics.Providers.Common.Cuda |
||||
|
{ |
||||
|
internal static class CudaProvider |
||||
|
{ |
||||
|
static int _nativeRevision; |
||||
|
static bool _nativeX86; |
||||
|
static bool _nativeX64; |
||||
|
static bool _nativeIA64; |
||||
|
|
||||
|
public static bool IsAvailable(int minRevision) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (!NativeProviderLoader.TryLoad(SafeNativeMethods.DllName)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
int a = SafeNativeMethods.query_capability(0); |
||||
|
int b = SafeNativeMethods.query_capability(1); |
||||
|
int nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); |
||||
|
return a == 0 && b == -1 && nativeRevision >= minRevision; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void Load(int minRevision) |
||||
|
{ |
||||
|
int a, b; |
||||
|
try |
||||
|
{ |
||||
|
NativeProviderLoader.TryLoad(SafeNativeMethods.DllName); |
||||
|
|
||||
|
a = SafeNativeMethods.query_capability(0); |
||||
|
b = SafeNativeMethods.query_capability(1); |
||||
|
_nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); |
||||
|
|
||||
|
_nativeX86 = SafeNativeMethods.query_capability((int)ProviderPlatform.x86) > 0; |
||||
|
_nativeX64 = SafeNativeMethods.query_capability((int)ProviderPlatform.x64) > 0; |
||||
|
_nativeIA64 = SafeNativeMethods.query_capability((int)ProviderPlatform.ia64) > 0; |
||||
|
} |
||||
|
catch (DllNotFoundException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("Cuda Native Provider not found.", e); |
||||
|
} |
||||
|
catch (BadImageFormatException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("Cuda Native Provider found but failed to load. Please verify that the platform matches (x64 vs x32, Windows vs Linux).", e); |
||||
|
} |
||||
|
catch (EntryPointNotFoundException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("Cuda Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e); |
||||
|
} |
||||
|
|
||||
|
if (a != 0 || b != -1 || _nativeRevision < minRevision) |
||||
|
{ |
||||
|
throw new NotSupportedException("Cuda Native Provider too old. Consider upgrading to a newer version."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static string Describe() |
||||
|
{ |
||||
|
var parts = new List<string>(); |
||||
|
if (_nativeX86) parts.Add("x86"); |
||||
|
if (_nativeX64) parts.Add("x64"); |
||||
|
if (_nativeIA64) parts.Add("IA64"); |
||||
|
parts.Add("revision " + _nativeRevision); |
||||
|
|
||||
|
return string.Concat("Nvidia CUDA (", string.Join("; ", parts), ")"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif
|
||||
@ -0,0 +1,262 @@ |
|||||
|
// <copyright file="MklProvider.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>
|
||||
|
|
||||
|
#if NATIVE
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace MathNet.Numerics.Providers.Common.Mkl |
||||
|
{ |
||||
|
internal static class MklProvider |
||||
|
{ |
||||
|
static Version _mklVersion; |
||||
|
static int _nativeRevision; |
||||
|
static bool _nativeX86; |
||||
|
static bool _nativeX64; |
||||
|
static bool _nativeIA64; |
||||
|
|
||||
|
public static bool IsAvailable(int minRevision) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (!NativeProviderLoader.TryLoad(SafeNativeMethods.DllName)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
int a = SafeNativeMethods.query_capability(0); |
||||
|
int b = SafeNativeMethods.query_capability(1); |
||||
|
int nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); |
||||
|
return a == 0 && b == -1 && nativeRevision >= minRevision; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void Load(int minRevision) |
||||
|
{ |
||||
|
int a, b; |
||||
|
try |
||||
|
{ |
||||
|
NativeProviderLoader.TryLoad(SafeNativeMethods.DllName); |
||||
|
|
||||
|
a = SafeNativeMethods.query_capability(0); |
||||
|
b = SafeNativeMethods.query_capability(1); |
||||
|
_nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); |
||||
|
|
||||
|
_nativeX86 = SafeNativeMethods.query_capability((int)ProviderPlatform.x86) > 0; |
||||
|
_nativeX64 = SafeNativeMethods.query_capability((int)ProviderPlatform.x64) > 0; |
||||
|
_nativeIA64 = SafeNativeMethods.query_capability((int)ProviderPlatform.ia64) > 0; |
||||
|
|
||||
|
_mklVersion = new Version( |
||||
|
SafeNativeMethods.query_capability((int)ProviderConfig.MklMajorVersion), |
||||
|
SafeNativeMethods.query_capability((int)ProviderConfig.MklMinorVersion), |
||||
|
SafeNativeMethods.query_capability((int)ProviderConfig.MklUpdateVersion)); |
||||
|
} |
||||
|
catch (DllNotFoundException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("MKL Native Provider not found.", e); |
||||
|
} |
||||
|
catch (BadImageFormatException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("MKL Native Provider found but failed to load. Please verify that the platform matches (x64 vs x32, Windows vs Linux).", e); |
||||
|
} |
||||
|
catch (EntryPointNotFoundException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("MKL Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e); |
||||
|
} |
||||
|
|
||||
|
if (a != 0 || b != -1 || _nativeRevision < minRevision) |
||||
|
{ |
||||
|
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() |
||||
|
{ |
||||
|
var parts = new List<string>(); |
||||
|
if (_nativeX86) parts.Add("x86"); |
||||
|
if (_nativeX64) parts.Add("x64"); |
||||
|
if (_nativeIA64) parts.Add("IA64"); |
||||
|
parts.Add("revision " + _nativeRevision); |
||||
|
if (_mklVersion.Major > 0) |
||||
|
{ |
||||
|
parts.Add(_mklVersion.Build == 0 |
||||
|
? string.Concat("MKL ", _mklVersion.ToString(2)) |
||||
|
: string.Concat("MKL ", _mklVersion.ToString(2), " Update ", _mklVersion.Build)); |
||||
|
} |
||||
|
|
||||
|
return string.Concat("Intel MKL (", string.Join("; ", parts), ")"); |
||||
|
} |
||||
|
|
||||
|
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 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif
|
||||
@ -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 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
// <copyright file="OpenBlasProvider.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>
|
||||
|
|
||||
|
#if NATIVE
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace MathNet.Numerics.Providers.Common.OpenBlas |
||||
|
{ |
||||
|
internal static class OpenBlasProvider |
||||
|
{ |
||||
|
static int _nativeRevision; |
||||
|
static bool _nativeX86; |
||||
|
static bool _nativeX64; |
||||
|
static bool _nativeIA64; |
||||
|
static bool _nativeARM; |
||||
|
|
||||
|
public static bool IsAvailable(int minRevision) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (!NativeProviderLoader.TryLoad(SafeNativeMethods.DllName)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
int a = SafeNativeMethods.query_capability(0); |
||||
|
int b = SafeNativeMethods.query_capability(1); |
||||
|
int nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); |
||||
|
return a == 0 && b == -1 && nativeRevision >= minRevision; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void Load(int minRevision) |
||||
|
{ |
||||
|
int a, b; |
||||
|
try |
||||
|
{ |
||||
|
NativeProviderLoader.TryLoad(SafeNativeMethods.DllName); |
||||
|
|
||||
|
a = SafeNativeMethods.query_capability(0); |
||||
|
b = SafeNativeMethods.query_capability(1); |
||||
|
_nativeRevision = SafeNativeMethods.query_capability((int)ProviderConfig.Revision); |
||||
|
|
||||
|
_nativeX86 = SafeNativeMethods.query_capability((int)ProviderPlatform.x86) > 0; |
||||
|
_nativeX64 = SafeNativeMethods.query_capability((int)ProviderPlatform.x64) > 0; |
||||
|
_nativeIA64 = SafeNativeMethods.query_capability((int)ProviderPlatform.ia64) > 0; |
||||
|
_nativeARM = SafeNativeMethods.query_capability((int)ProviderPlatform.arm) > 0; |
||||
|
} |
||||
|
catch (DllNotFoundException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("OpenBLAS Native Provider not found.", e); |
||||
|
} |
||||
|
catch (BadImageFormatException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("OpenBLAS Native Provider found but failed to load. Please verify that the platform matches (x64 vs x32, Windows vs Linux).", e); |
||||
|
} |
||||
|
catch (EntryPointNotFoundException e) |
||||
|
{ |
||||
|
throw new NotSupportedException("OpenBLAS Native Provider does not support capability querying and is therefore not compatible. Consider upgrading to a newer version.", e); |
||||
|
} |
||||
|
|
||||
|
if (a != 0 || b != -1 || _nativeRevision < minRevision) |
||||
|
{ |
||||
|
throw new NotSupportedException("OpenBLAS 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 string Describe() |
||||
|
{ |
||||
|
var parts = new List<string>(); |
||||
|
if (_nativeX86) parts.Add("x86"); |
||||
|
if (_nativeX64) parts.Add("x64"); |
||||
|
if (_nativeIA64) parts.Add("IA64"); |
||||
|
if (_nativeARM) parts.Add("ARM"); |
||||
|
parts.Add("revision " + _nativeRevision); |
||||
|
|
||||
|
return string.Concat("OpenBLAS (", string.Join("; ", parts), ")"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif
|
||||
@ -0,0 +1,101 @@ |
|||||
|
// <copyright file="FourierTransformControl.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.FourierTransform |
||||
|
{ |
||||
|
internal static class FourierTransformControl |
||||
|
{ |
||||
|
const string EnvVarFFTProvider = "MathNetNumericsFFTProvider"; |
||||
|
|
||||
|
public static void UseManaged() |
||||
|
{ |
||||
|
Control.FourierTransformProvider = new ManagedFourierTransformProvider(); |
||||
|
} |
||||
|
|
||||
|
#if NATIVE
|
||||
|
public static void UseNativeMKL() |
||||
|
{ |
||||
|
Control.FourierTransformProvider = new Mkl.MklFourierTransformProvider(); |
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
public static bool TryUse(IFourierTransformProvider provider) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (!provider.IsAvailable()) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
Control.FourierTransformProvider = provider; |
||||
|
return true; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
// intentionally swallow exceptions here - use the explicit variants if you're interested in why
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void UseBest() |
||||
|
{ |
||||
|
#if NATIVE
|
||||
|
if (!TryUse(new Mkl.MklFourierTransformProvider())) |
||||
|
{ |
||||
|
UseManaged(); |
||||
|
} |
||||
|
#else
|
||||
|
UseManaged(); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
public static void UseDefault() |
||||
|
{ |
||||
|
#if NATIVE
|
||||
|
var value = Environment.GetEnvironmentVariable(EnvVarFFTProvider); |
||||
|
switch (value != null ? value.ToUpperInvariant() : string.Empty) |
||||
|
{ |
||||
|
|
||||
|
case "MKL": |
||||
|
UseNativeMKL(); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
UseBest(); |
||||
|
break; |
||||
|
} |
||||
|
#else
|
||||
|
UseManaged(); |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
// <copyright file="IFourierTransformProvider.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>
|
||||
|
|
||||
|
namespace MathNet.Numerics.Providers.FourierTransform |
||||
|
{ |
||||
|
|
||||
|
#if !NOSYSNUMERICS
|
||||
|
using Complex = System.Numerics.Complex; |
||||
|
#endif
|
||||
|
|
||||
|
public enum FourierTransformScaling : int |
||||
|
{ |
||||
|
NoScaling = 0, |
||||
|
SymmetricScaling = 1, |
||||
|
BackwardScaling = 2, |
||||
|
ForwardScaling = 3 |
||||
|
} |
||||
|
|
||||
|
public interface IFourierTransformProvider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Try to find out whether the provider is available, at least in principle.
|
||||
|
/// Verification may still fail if available, but it will certainly fail if unavailable.
|
||||
|
/// </summary>
|
||||
|
bool IsAvailable(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider
|
||||
|
/// </summary>
|
||||
|
void InitializeVerify(); |
||||
|
|
||||
|
void ForwardInplace(Complex[] complex, FourierTransformScaling scaling); |
||||
|
void BackwardInplace(Complex[] complex, FourierTransformScaling scaling); |
||||
|
|
||||
|
Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling); |
||||
|
Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
// <copyright file="ManagedFourierTransformProvider.cs" company="Math.NET">
|
||||
|
// Math.NET Numerics, part of the Math.NET Project
|
||||
|
// http://mathnet.opensourcedotnet.info
|
||||
|
//
|
||||
|
// 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.Collections; |
||||
|
using MathNet.Numerics.IntegralTransforms; |
||||
|
|
||||
|
namespace MathNet.Numerics.Providers.FourierTransform |
||||
|
{ |
||||
|
|
||||
|
#if !NOSYSNUMERICS
|
||||
|
using Complex = System.Numerics.Complex; |
||||
|
#endif
|
||||
|
|
||||
|
public class ManagedFourierTransformProvider : IFourierTransformProvider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Try to find out whether the provider is available, at least in principle.
|
||||
|
/// Verification may still fail if available, but it will certainly fail if unavailable.
|
||||
|
/// </summary>
|
||||
|
public bool IsAvailable() |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider
|
||||
|
/// </summary>
|
||||
|
public void InitializeVerify() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public string ToString() |
||||
|
{ |
||||
|
return "Managed"; |
||||
|
} |
||||
|
|
||||
|
public void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
switch (scaling) |
||||
|
{ |
||||
|
case FourierTransformScaling.SymmetricScaling: |
||||
|
Fourier.BluesteinForward(complex, FourierOptions.Default); |
||||
|
break; |
||||
|
case FourierTransformScaling.ForwardScaling: |
||||
|
// Only backward scaling can be expressed with options, hence the double-inverse
|
||||
|
Fourier.BluesteinInverse(complex, FourierOptions.AsymmetricScaling | FourierOptions.InverseExponent); |
||||
|
break; |
||||
|
default: |
||||
|
Fourier.BluesteinForward(complex, FourierOptions.NoScaling); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void BackwardInplace(Complex[] complex, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
switch (scaling) |
||||
|
{ |
||||
|
case FourierTransformScaling.SymmetricScaling: |
||||
|
Fourier.BluesteinInverse(complex, FourierOptions.Default); |
||||
|
break; |
||||
|
case FourierTransformScaling.BackwardScaling: |
||||
|
Fourier.BluesteinInverse(complex, FourierOptions.AsymmetricScaling); |
||||
|
break; |
||||
|
default: |
||||
|
Fourier.BluesteinInverse(complex, FourierOptions.NoScaling); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
Complex[] work = new Complex[complexTimeSpace.Length]; |
||||
|
complexTimeSpace.Copy(work); |
||||
|
ForwardInplace(work, scaling); |
||||
|
return work; |
||||
|
} |
||||
|
|
||||
|
public Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
Complex[] work = new Complex[complexFrequenceSpace.Length]; |
||||
|
complexFrequenceSpace.Copy(work); |
||||
|
BackwardInplace(work, scaling); |
||||
|
return work; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,183 @@ |
|||||
|
// <copyright file="MklFourierTransformProvider.cs" company="Math.NET">
|
||||
|
// Math.NET Numerics, part of the Math.NET Project
|
||||
|
// http://mathnet.opensourcedotnet.info
|
||||
|
//
|
||||
|
// 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>
|
||||
|
|
||||
|
#if NATIVE
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
using MathNet.Numerics.Providers.Common.Mkl; |
||||
|
|
||||
|
namespace MathNet.Numerics.Providers.FourierTransform.Mkl |
||||
|
{ |
||||
|
public class MklFourierTransformProvider : IFourierTransformProvider |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Try to find out whether the provider is available, at least in principle.
|
||||
|
/// Verification may still fail if available, but it will certainly fail if unavailable.
|
||||
|
/// </summary>
|
||||
|
public bool IsAvailable() |
||||
|
{ |
||||
|
return MklProvider.IsAvailable(minRevision: 11); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initialize and verify that the provided is indeed available. If not, fall back to alternatives like the managed provider
|
||||
|
/// </summary>
|
||||
|
public void InitializeVerify() |
||||
|
{ |
||||
|
MklProvider.Load(minRevision: 11); |
||||
|
|
||||
|
// we only support exactly one major version, since major version changes imply a breaking change.
|
||||
|
int fftMajor = SafeNativeMethods.query_capability((int)ProviderCapability.FourierTransformMajor); |
||||
|
int fftMinor = SafeNativeMethods.query_capability((int)ProviderCapability.FourierTransformMinor); |
||||
|
if (!(fftMajor == 1 && fftMinor >= 0)) |
||||
|
{ |
||||
|
throw new NotSupportedException(string.Format("MKL Native Provider not compatible. Expecting fourier transform v1 but provider implements v{0}.", fftMajor)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <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(); |
||||
|
} |
||||
|
|
||||
|
public void ForwardInplace(Complex[] complex, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
SafeNativeMethods.z_fft_forward_inplace(complex.Length, ForwardScaling(scaling, complex.Length), complex); |
||||
|
} |
||||
|
|
||||
|
public void BackwardInplace(Complex[] complex, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
SafeNativeMethods.z_fft_backward_inplace(complex.Length, BackwardScaling(scaling, complex.Length), complex); |
||||
|
} |
||||
|
|
||||
|
public Complex[] Forward(Complex[] complexTimeSpace, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
Complex[] work = new Complex[complexTimeSpace.Length]; |
||||
|
complexTimeSpace.Copy(work); |
||||
|
ForwardInplace(work, scaling); |
||||
|
return work; |
||||
|
} |
||||
|
|
||||
|
public Complex[] Backward(Complex[] complexFrequenceSpace, FourierTransformScaling scaling) |
||||
|
{ |
||||
|
Complex[] work = new Complex[complexFrequenceSpace.Length]; |
||||
|
complexFrequenceSpace.Copy(work); |
||||
|
BackwardInplace(work, scaling); |
||||
|
return work; |
||||
|
} |
||||
|
|
||||
|
static double ForwardScaling(FourierTransformScaling scaling, int length) |
||||
|
{ |
||||
|
switch (scaling) |
||||
|
{ |
||||
|
case FourierTransformScaling.SymmetricScaling: |
||||
|
return Math.Sqrt(1.0/length); |
||||
|
case FourierTransformScaling.ForwardScaling: |
||||
|
return 1.0/length; |
||||
|
default: |
||||
|
return 1.0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static double BackwardScaling(FourierTransformScaling scaling, int length) |
||||
|
{ |
||||
|
switch (scaling) |
||||
|
{ |
||||
|
case FourierTransformScaling.SymmetricScaling: |
||||
|
return Math.Sqrt(1.0/length); |
||||
|
case FourierTransformScaling.BackwardScaling: |
||||
|
return 1.0/length; |
||||
|
default: |
||||
|
return 1.0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif
|
||||
@ -0,0 +1,122 @@ |
|||||
|
// <copyright file="LinearAlgebraControl.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.LinearAlgebra |
||||
|
{ |
||||
|
internal static class LinearAlgebraControl |
||||
|
{ |
||||
|
const string EnvVarLAProvider = "MathNetNumericsLAProvider"; |
||||
|
|
||||
|
public static void UseManaged() |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider = new ManagedLinearAlgebraProvider(); |
||||
|
} |
||||
|
|
||||
|
#if NATIVE
|
||||
|
public static void UseNativeMKL( |
||||
|
Common.Mkl.MklConsistency consistency = Common.Mkl.MklConsistency.Auto, |
||||
|
Common.Mkl.MklPrecision precision = Common.Mkl.MklPrecision.Double, |
||||
|
Common.Mkl.MklAccuracy accuracy = Common.Mkl.MklAccuracy.High) |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider = new Mkl.MklLinearAlgebraProvider(consistency, precision, accuracy); |
||||
|
} |
||||
|
|
||||
|
public static void UseNativeCUDA() |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider = new Cuda.CudaLinearAlgebraProvider(); |
||||
|
} |
||||
|
|
||||
|
public static void UseNativeOpenBLAS() |
||||
|
{ |
||||
|
Control.LinearAlgebraProvider = new OpenBlas.OpenBlasLinearAlgebraProvider(); |
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
public static bool TryUse(ILinearAlgebraProvider provider) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (!provider.IsAvailable()) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
Control.LinearAlgebraProvider = provider; |
||||
|
return true; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
// intentionally swallow exceptions here - use the explicit variants if you're interested in why
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void UseBest() |
||||
|
{ |
||||
|
#if NATIVE
|
||||
|
if (!(TryUse(new Cuda.CudaLinearAlgebraProvider()) |
||||
|
|| TryUse(new Mkl.MklLinearAlgebraProvider()) |
||||
|
|| TryUse(new OpenBlas.OpenBlasLinearAlgebraProvider()))) |
||||
|
{ |
||||
|
UseManaged(); |
||||
|
} |
||||
|
#else
|
||||
|
UseManaged(); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
public static void UseDefault() |
||||
|
{ |
||||
|
#if NATIVE
|
||||
|
var value = Environment.GetEnvironmentVariable(EnvVarLAProvider); |
||||
|
switch (value != null ? value.ToUpperInvariant() : string.Empty) |
||||
|
{ |
||||
|
case "MKL": |
||||
|
UseNativeMKL(); |
||||
|
break; |
||||
|
|
||||
|
case "CUDA": |
||||
|
UseNativeCUDA(); |
||||
|
break; |
||||
|
|
||||
|
case "OPENBLAS": |
||||
|
UseNativeOpenBLAS(); |
||||
|
break; |
||||
|
default: |
||||
|
UseBest(); |
||||
|
break; |
||||
|
} |
||||
|
#else
|
||||
|
UseManaged(); |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,103 @@ |
|||||
|
// <copyright file="FourierTransformProviderTests.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; |
||||
|
using MathNet.Numerics.Distributions; |
||||
|
using MathNet.Numerics.Providers.FourierTransform; |
||||
|
using MathNet.Numerics.Statistics; |
||||
|
using NUnit.Framework; |
||||
|
|
||||
|
namespace MathNet.Numerics.UnitTests.FourierTransformProviderTests |
||||
|
{ |
||||
|
#if NOSYSNUMERICS
|
||||
|
using Complex = Numerics.Complex; |
||||
|
#else
|
||||
|
using Complex = System.Numerics.Complex; |
||||
|
#endif
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Base class for linear algebra provider tests.
|
||||
|
/// </summary>
|
||||
|
[TestFixture, Category("LAProvider")] |
||||
|
public class LinearAlgebraProviderTests |
||||
|
{ |
||||
|
[Test] |
||||
|
public void ForwardInplaceRealSine() |
||||
|
{ |
||||
|
var samples = Generate.PeriodicMap(16, w => new Complex(Math.Sin(w), 0), 16, 1.0, Constants.Pi2); |
||||
|
var spectrum = new Complex[samples.Length]; |
||||
|
|
||||
|
// real-odd transforms to imaginary odd
|
||||
|
samples.Copy(spectrum); |
||||
|
Control.FourierTransformProvider.ForwardInplace(spectrum, FourierTransformScaling.BackwardScaling); |
||||
|
|
||||
|
// all real components must be zero
|
||||
|
foreach (var c in spectrum) |
||||
|
{ |
||||
|
Assert.AreEqual(0, c.Real, 1e-12, "real"); |
||||
|
} |
||||
|
|
||||
|
// all imaginary components except second and last musth be zero
|
||||
|
for (var i = 0; i < spectrum.Length; i++) |
||||
|
{ |
||||
|
if (i == 1) |
||||
|
{ |
||||
|
Assert.AreEqual(-8, spectrum[i].Imaginary, 1e-12, "imag second"); |
||||
|
} |
||||
|
else if (i == spectrum.Length - 1) |
||||
|
{ |
||||
|
Assert.AreEqual(8, spectrum[i].Imaginary, 1e-12, "imag last"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
Assert.AreEqual(0, spectrum[i].Imaginary, 1e-12, "imag"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[TestCase(0x1000)] |
||||
|
[TestCase(0x7FF)] |
||||
|
public void ForwardInplaceParsevalTheorem(int count) |
||||
|
{ |
||||
|
var samples = Generate.RandomComplex(count, GetUniform(1)); |
||||
|
var timeSpaceEnergy = Generate.Map(samples, s => s.MagnitudeSquared()).Mean(); |
||||
|
|
||||
|
Control.FourierTransformProvider.ForwardInplace(samples, FourierTransformScaling.SymmetricScaling); |
||||
|
var frequencySpaceEnergy = Generate.Map(samples, s => s.MagnitudeSquared()).Mean(); |
||||
|
|
||||
|
Assert.AreEqual(timeSpaceEnergy, frequencySpaceEnergy, 1e-12); |
||||
|
} |
||||
|
|
||||
|
IContinuousDistribution GetUniform(int seed) |
||||
|
{ |
||||
|
return new ContinuousUniform(-1, 1, new System.Random(seed)); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue