Skip to content

DFTI performance improvement #32

Open

Description

@TobiasErnst

In the current implementation of MKL.NET a descriptor is created for every DFT.
If you need to run similar DFTs with only different data this results in a not needed overhead due to memory allocations.

Therefore the methods DftiCreateDescriptor and DftiFreeDescriptor should also be accessible via MKL.NET and it should be possible to inject an already created descriptor to all other Dfti methods.

I am willing to implement this but I currently have a problem with the Package-Native.ps1 whish throws the error

Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (403) Forbidden."
At D:\MKL.NET\Scripts\Package-Native.ps1:22 char:9
+         $wc.DownloadFile($source, $localFilename)
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException

for
DownloadFile https://registrationcenter-download.intel.com/akdlm/irc_nas/18444/l_onemkl_p_2022.0.1.117_offline.sh "$PSScriptRoot/../packages/l_onemkl_p_2022.0.1.117_offline.sh"

Activity

  1. atlemann commented on Apr 9, 2026

    @atlemann
    Contributor

    I'm currently trying to create C# methods for calling the DftiCreateDescriptor in a library, since I need single precision 3D FFT and thought it was most flexible to just expose all the Dfti methods in C# and perhaps add them to this project. But I just can't get it to work in my lib. Every time my code hits the DftiCreateDescriptor from C#, it crashes immediately with a 132 exit code.

  2. TSerious commented on Apr 10, 2026

    @TSerious

    @atlemann you can checkout my repo: oneMKL.FFT.NET
    It has most of the Dfti methods exposed.

  3. atlemann commented on Apr 10, 2026

    @atlemann
    Contributor

    Looks very similar to what I tried. Perhaps it's some nuance with NixOS. Looks like you're targeting Windows?

  4. TSerious commented on Apr 10, 2026

    @TSerious

    Yes, that's right.
    I already thought about integrating what I did into MKL.NET, but the last time I tried I was not able to get it compiling (see the first post in this request).

  5. atlemann commented on Apr 10, 2026

    @atlemann
    Contributor

    Looks like some parts of the FFTW api's are available, e.g. fftwf_plan_dft_3d which gives you a pointer to a plan for single precision 3D FFT. https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-fortran/2023-0/using-fftw3-wrappers.html

    So you can define these:

    private const int FFTW_FORWARD = -1;
    private const int FFTW_BACKWARD = 1;
    private const uint FFTW_ESTIMATE = 64;
    
    [DllImport(Mkl.DllFile, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
    static extern IntPtr fftwf_plan_dft_3d(int nx, int ny, int nz, void* @in, void* @out, int sign, uint flags);
    
    [DllImport(Mkl.DllFile, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
    static extern void fftwf_execute(IntPtr plan);
    
    [DllImport(Mkl.DllFile, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
    static extern void fftwf_destroy_plan(IntPtr plan);

    and call it like this:

    private static void Compute3D(void* matrixData, int nx, int ny, int nz, bool forward)
    {
        var plan = IntPtr.Zero;
        try
        {
            int sign = forward ? FFTW_FORWARD : FFTW_BACKWARD;
            plan = fftwf_plan_dft_3d(nx, ny, nz, matrixData, matrixData, sign, FFTW_ESTIMATE); // FFTW_ESTIMATE is ignored, according to the docs
            if (plan == IntPtr.Zero)
                throw new InvalidOperationException("Failed to create FFTW plan");
    
            fftwf_execute(plan);
    
            // Scale for inverse FFT
            if (!forward)
            {
                var scale = 1.0f / ((float)nx * ny * nz);
                // Unsafe, since I've already fixed matixData outside this function
                Blas.Unsafe.scal(nx * ny * nz * 2, scale, (float*)matrixData, 1);
            }
        }
        finally
        {
            if (plan != IntPtr.Zero)
                fftwf_destroy_plan(plan);
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions