Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Dotnet Machinelearning MklFftProxy

From Leeroopedia


Knowledge Sources
Domains Signal Processing, Native Interop, Time Series Analysis
Last Updated 2026-02-09 12:00 GMT

Overview

Proxy wrapper library that adapts Intel MKL's variadic DFTI (Discrete Fourier Transform Interface) API into fixed-argument C functions callable from C# via P/Invoke, enabling FFT-based time series analysis in ML.NET.

Description

MklProxyNative.cpp solves a specific interop challenge: Intel MKL's DFTI functions use C variadic arguments (...) in several key functions, particularly DftiSetValue and DftiCreateDescriptor. The .NET P/Invoke marshaller cannot reliably call variadic native functions because the calling convention and argument promotion rules differ from fixed-argument functions on many platforms.

This proxy library wraps each variadic MKL function with a fixed-argument equivalent:

  • MKLDftiSetValue wraps DftiSetValue -- accepts the configuration parameter enum and value as explicit typed arguments instead of variadic arguments
  • MKLDftiCreateDescriptor wraps DftiCreateDescriptor -- accepts precision, domain, dimensionality, and sizes as explicit arguments
  • MKLDftiComputeForward wraps DftiComputeForward -- accepts separate real and imaginary input/output buffers for split-complex format
  • MKLDftiComputeBackward wraps DftiComputeBackward -- accepts separate real and imaginary input/output buffers for the inverse transform

The library also defines C-compatible enumerations (ConfigParam and ConfigValue) that mirror MKL's DFTI enums, providing a stable ABI that does not depend on MKL header versioning.

Usage

This proxy is used internally by ML.NET's time series analysis components, specifically:

  • Singular Spectrum Analysis (SSA) forecasting, which uses FFT to efficiently compute the Hankel matrix eigendecomposition
  • Fourier-based seasonality detection, which identifies dominant frequency components in time series data
  • Any ML.NET transform or trainer that requires frequency-domain signal processing

Code Reference

Source Location

Signature

// Configuration parameter enumeration
enum ConfigParam {
    ForwardDomain = 0,
    Dimension = 1,
    Precision = 2,
    ForwardScale = 4,
    BackwardScale = 5,
    NumberOfTransforms = 7,
    NumberOfUserThreads = 8,
    InputDistance = 12,
    OutputDistance = 13,
    Placement = 11,
    ComplexStorage = 14,
    RealStorage = 15,
    ConjugateEvenStorage = 16,
    PackedFormat = 21,
    Workspace = 26,
    CommitStatus = 22
};

// Configuration value enumeration
enum ConfigValue {
    Committed = 0,
    Uncommitted = 1,
    Complex = 32,
    Real = 33,
    Single = 35,
    Double = 36,
    ComplexComplex = 39,
    RealReal = 42,
    Inplace = 43,
    NotInplace = 44,
    Allow = 51,
    Avoid = 52,
    None = 53
};

// Exported proxy functions
EXPORT_API(int) MKLDftiSetValue(
    DFTI_DESCRIPTOR_HANDLE handle,
    int config_param,
    int config_val
);

EXPORT_API(int) MKLDftiCreateDescriptor(
    DFTI_DESCRIPTOR_HANDLE* handle,
    int precision,
    int domain,
    int dim,
    int* sizes
);

EXPORT_API(int) MKLDftiComputeForward(
    DFTI_DESCRIPTOR_HANDLE handle,
    float* inputRe,
    float* inputIm,
    float* outputRe,
    float* outputIm
);

EXPORT_API(int) MKLDftiComputeBackward(
    DFTI_DESCRIPTOR_HANDLE handle,
    float* inputRe,
    float* inputIm,
    float* outputRe,
    float* outputIm
);

Import

// P/Invoke declarations (managed side)
[DllImport("MklProxyNative")]
internal static extern int MKLDftiCreateDescriptor(
    out IntPtr handle, int precision, int domain,
    int dim, int[] sizes);

[DllImport("MklProxyNative")]
internal static extern int MKLDftiSetValue(
    IntPtr handle, int configParam, int configVal);

[DllImport("MklProxyNative")]
internal static extern int MKLDftiComputeForward(
    IntPtr handle,
    float[] inputRe, float[] inputIm,
    float[] outputRe, float[] outputIm);

[DllImport("MklProxyNative")]
internal static extern int MKLDftiComputeBackward(
    IntPtr handle,
    float[] inputRe, float[] inputIm,
    float[] outputRe, float[] outputIm);

// MKL also requires explicit commit and free calls
[DllImport("MklProxyNative")]
internal static extern int DftiCommitDescriptor(IntPtr handle);

[DllImport("MklProxyNative")]
internal static extern int DftiFreeDescriptor(ref IntPtr handle);

I/O Contract

Inputs

Name Type Required Description
handle DFTI_DESCRIPTOR_HANDLE Yes Opaque handle to an MKL FFT descriptor (created by MKLDftiCreateDescriptor)
config_param int (ConfigParam enum) Yes (SetValue) Which configuration property to set (e.g., Placement, ForwardScale)
config_val int (ConfigValue enum) Yes (SetValue) The value to assign to the configuration property
precision int Yes (Create) Floating-point precision: Single (35) or Double (36)
domain int Yes (Create) Transform domain: Complex (32) or Real (33)
dim int Yes (Create) Dimensionality of the transform (1 for 1-D FFT)
sizes int* Yes (Create) Array of dimension sizes; for 1-D, a single element specifying transform length
inputRe float* Yes (Compute) Real part of the input signal
inputIm float* Yes (Compute) Imaginary part of the input signal (zeros for real-valued input)
outputRe float* Yes (Compute) Buffer for the real part of the output
outputIm float* Yes (Compute) Buffer for the imaginary part of the output

Outputs

Name Type Description
return (all functions) int MKL status code: 0 indicates success; non-zero indicates an error (see MKL DFTI error codes)
handle (Create) DFTI_DESCRIPTOR_HANDLE* Output parameter: pointer to the created descriptor handle
outputRe (Compute) float* Real part of the transformed signal
outputIm (Compute) float* Imaginary part of the transformed signal

FFT Workflow

The typical usage sequence for performing an FFT through this proxy is:

  1. Create a descriptor with MKLDftiCreateDescriptor (specify precision, domain, and transform size)
  2. Configure the descriptor with one or more calls to MKLDftiSetValue (e.g., set placement to not-in-place, set storage format)
  3. Commit the descriptor with DftiCommitDescriptor (finalizes internal plans and allocations)
  4. Compute the forward or backward transform with MKLDftiComputeForward or MKLDftiComputeBackward
  5. Free the descriptor with DftiFreeDescriptor when no longer needed

Usage Examples

// Performing a 1-D forward FFT using the MKL proxy
IntPtr handle;
int[] sizes = new int[] { signalLength };

// Step 1: Create descriptor for single-precision, real domain, 1-D
MKLDftiCreateDescriptor(out handle, 35 /* Single */, 33 /* Real */, 1, sizes);

// Step 2: Configure for not-in-place computation
MKLDftiSetValue(handle, 11 /* Placement */, 44 /* NotInplace */);

// Step 3: Commit the descriptor
DftiCommitDescriptor(handle);

// Step 4: Compute forward FFT
float[] inputRe = signal;
float[] inputIm = new float[signalLength]; // zeros
float[] outputRe = new float[signalLength];
float[] outputIm = new float[signalLength];

MKLDftiComputeForward(handle, inputRe, inputIm, outputRe, outputIm);

// outputRe and outputIm now contain the frequency-domain representation

// Step 5: Free descriptor
DftiFreeDescriptor(ref handle);
// Used internally by ML.NET SSA forecasting
var pipeline = mlContext.Forecasting.ForecastBySsa(
    outputColumnName: "Forecast",
    inputColumnName: "Value",
    windowSize: 12,
    seriesLength: 36,
    trainSize: 120,
    horizon: 6);

// The SSA trainer internally uses MKL FFT via this proxy
// to compute eigenvalues of the trajectory matrix
var model = pipeline.Fit(trainingData);

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment