Intel® oneAPI Math Kernel Library
Ask questions and share information with other developers who use Intel® Math Kernel Library.

FFT MKL with C#

Gianluca_G_1
Beginner
1,056 Views

Hello,
I'm trying to use the FFT MKL (ver. 11.3.3.1) functionality in C# (VS2015), but I'm facing problems that I can  not solve after hours of research and tests. 

In particular the DftiSetValue() continues to return different error messages:
"Inconsistent configuration parameter" or if I change the declaration parameters ...
"Functionality is not implemented".


I attach the program MKLTest that I use to learn and test the MKL functions.
See the button "FFT"  in MainForm (I'm tryng the FFT functionality).
In file files_fft.zip I have some file used to try DftiComputeBackward().

Thank you very much

Gianluca

0 Kudos
10 Replies
Zhen_Z_Intel
Employee
1,056 Views

Hi Gianluca,

It seems the Nuget package has been used for System.Numerics. I check with packages.config, it is empty. Could you please provide packages.config with content so that I could reproduce your problem. Thanks.

Best regards,
Fiona

0 Kudos
Gianluca_G_1
Beginner
1,056 Views

Sorry,

you can remove the package file ("packages.config"), no package is used in the project.

BR

Gianluca

 

0 Kudos
Dmitry_Z_Intel1
Employee
1,056 Views

Hi Gianluca,

The problem is you create descriptor for DFTI_REAL, what means that you can't use DFTI_COMPLEX_STORAGE as it's not supproted for DFTI_REAL type.

Please refer to the page described possible storage variables.

https://software.intel.com/en-us/node/521970#24AAA0B1-A87C-4CAE-921E-E2118A0692AE

Guess you need DFTI_CONJUGATE_EVEN_STORAGE.

 

Thanks,

Dmitry.

0 Kudos
Gianluca_G_1
Beginner
1,056 Views

Ok thank you,

Now the procedure works without errors ...


By the way now the results are zero!

I pass a Complex[,] array and I expect to obtain a Real one.
What is wrong?

Thank you

0 Kudos
Dmitry_Z_Intel1
Employee
1,056 Views

Hi Gianluca,

I see a slight confusion in attached code.

The thing is you use 4 arrays passing to compute: status = DftiComputeBackward(des_handle, yre_in, yim_in, xre_out, xim_out); //Compute the Backward FFT

But this usage of 4 arrays is for only DFTI_COMPLEX forward domain in case when you do so-named "split-complex" FFT when your input data is separated: memory = input_real_parts + input_imaginary_parts.

So the question is "What exactly do you want to compute? What task do you solve?"

Thanks,

Dmitry.

0 Kudos
Gianluca_G_1
Beginner
1,056 Views

The second example MKLTest2 works because it doesn't give any error, but the results are wrong.
I tryed to make Backward and Forward FFT with the aim to understand how this functions works.

The final result should be the initial matrix but this is not true.
 

The input vector is a Complex one, it is a result of FFT Forward Transformation of a current transient in a time domain

While the output of DftiComputeBackward should be a real vector. 


The MKLTest program import the correct file, this is a complex vector, (see  button FFT) and try do make the FFTBackward.



 

Gianluca

 

0 Kudos
Dmitry_Z_Intel1
Employee
1,056 Views

I'm sorry, haven't updated the page before the reply.

I will take a look at your sources.

Thanks,

Dmitry.

 

Previous answer was:

Hi Gianluca,

I don't insist but probably if you just try MKL FFT API, it's better to look through MKL dftc examples. They show how to use API: how to create a descriptor, what additional parameters and values should be set for simple situations, like educational ones.

Hope this helps you to evaluate MKL.

Thank you,

Dmitry.

0 Kudos
Gianluca_G_1
Beginner
1,056 Views

sorry,

but the functions declarations its ok I was wrong.

By the way there is something I miss, maybe is because the documentation is not clear o maybe its me.

The documentation is for c++ code not exactly c#.

But before to contact you I've spent a lot of time to try myself.

As I wrote, I tried to make FFT Backward and FFT Forward expecting to return to the initial input matrix and this doesn't happen.

Thank you for any help

 

Best Regards

 

0 Kudos
Gianluca_G_1
Beginner
1,056 Views

well,

some one can tell me why this simple example doesn't provide the results I'm expecting.

Here the input and output (certified)

//INPUT
//REAL[0] = 1.000,   IMAG[0] = 0.000
//REAL[1] = 0.000,   IMAG[1] = 0.000
//REAL[2] = 0.000,   IMAG[2] = 0.000
//REAL[3] = 0.000,   IMAG[3] = 0.000
//REAL[4] = 0.000,   IMAG[4] = 0.000
//REAL[5] = 0.000,   IMAG[5] = 0.000
//REAL[6] = 0.000,   IMAG[6] = 0.000
//REAL[7] = 0.000,   IMAG[7] = 0.000

//RESULTS
//REAL[0] = 0.125,   IMAG[0] = 0.000
//REAL[1] = 0.125,   IMAG[1] = 0.000
//REAL[2] = 0.125,   IMAG[2] = 0.000
//REAL[3] = 0.125,   IMAG[3] = 0.000
//REAL[4] = 0.125,   IMAG[4] = 0.000
//REAL[5] = 0.125,   IMAG[5] = 0.000
//REAL[6] = 0.125,   IMAG[6] = 0.000
//REAL[7] = 0.125,   IMAG[7] = 0.000

//http://www.sccon.ca/sccon/fft/fft3.htm

 

          
These the operations I make in C#
 

public static Complex[,] MKL_FFT(double[] yre_in, double[] yim_in)
        {
            int status;
            IntPtr des_handle = IntPtr.Zero;
            int iN = yre_in.Length;
            int iN2 = iN / 2;
            int iSize = yre_in.Length;
           
            double[] xre_out = new double[iN2 + 1];
            double[] xim_out = new double[iN2 + 1];

            try
            {
                status = DftiCreateDescriptor(ref des_handle, (int)DFTI_CONFIG_VALUE.DFTI_DOUBLE, (int)DFTI_CONFIG_VALUE.DFTI_COMPLEX, 1, iN);
                               
                status = DftiSetValue(des_handle, (int)DFTI_CONFIG_PARAM.DFTI_PLACEMENT, __arglist((int)DFTI_CONFIG_VALUE.DFTI_NOT_INPLACE));
               
                status = DftiCommitDescriptor(des_handle); //Finalize the descriptor
               
                status = DftiComputeForward(des_handle, yre_in, yim_in, xre_out, xim_out); //Compute the Backward FFT
               
                status = DftiFreeDescriptor(ref des_handle); //Free the descriptor
               

                int[] lowerBounds = { 1, 1 };
                int[] lengths = { iN2 + 1, 1 };
                Complex[,] out_matrix = (Complex[,])Array.CreateInstance(typeof(Complex), lengths, lowerBounds);

                //populate result matrix
                for (int i = 1; i <= iN2 + 1; i++)
                {
                    out_matrix[i, 1] = new Complex(xre_out[i - 1], xim_out[i - 1]);
                }
                return out_matrix;
            }
            catch (Exception ex)
            {
                if (des_handle != IntPtr.Zero)
                    DftiFreeDescriptor(ref des_handle); //Free the descriptor
                throw ex;
            }

        }





 

 

0 Kudos
Gianluca_G_1
Beginner
1,056 Views

Now it works!!!!!

It was a declarative problem:

Here how to declare the API functions in C#:

#region FFT (DFTI)

        //DFTI_EXTERN char* DftiErrorMessage(MKL_LONG);
        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern IntPtr DftiErrorMessage(
            long error_code
        );

        //DFTI_EXTERN MKL_LONG DftiCreateDescriptor(DFTI_DESCRIPTOR_HANDLE*,
        //                      enum DFTI_CONFIG_VALUE, /* precision */
        //                      enum DFTI_CONFIG_VALUE, /* domain */
        //                      MKL_LONG, ...);
        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int DftiCreateDescriptor(
            ref IntPtr handle_descriptor,
            int precision,
            int domain,
            int dime,
            int size
        );
        
        //DFTI_EXTERN MKL_LONG DftiCommitDescriptor(DFTI_DESCRIPTOR_HANDLE);
        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int DftiCommitDescriptor(
            IntPtr handle_descriptor
        );

        //DFTI_EXTERN MKL_LONG DftiSetValue(DFTI_DESCRIPTOR_HANDLE, enum DFTI_CONFIG_PARAM, ...);
        [SuppressUnmanagedCodeSecurity]
        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int DftiSetValue(IntPtr handle_descriptor, int config_param, __arglist);

        //DFTI_EXTERN MKL_LONG DftiComputeBackward(DFTI_DESCRIPTOR_HANDLE, void*, ...);
        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int DftiComputeBackward(
            IntPtr handle_descriptor,
            [In] Complex[] x_in,
            [Out] Complex[] x_out
        );

        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int DftiComputeForward(
            IntPtr handle_descriptor,
            [In] Complex[] x_in,            
            [Out] Complex[] x_out
        );

        //DFTI_EXTERN MKL_LONG DftiFreeDescriptor(DFTI_DESCRIPTOR_HANDLE*);
        [DllImport("mkl_rt.dll", ExactSpelling = true, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
        internal static extern int DftiFreeDescriptor(
            ref IntPtr handle_descriptor
        );
        #endregion

 

 

Best Regards

 

Gianluca

 

0 Kudos
Reply