我要评分
获取效率
正确性
完整性
易理解

Migrating a Fast Fourier Transform (FFT) Library

Replaceability

The KML_FFT and MKL interfaces are different. Therefore, you need to replace the code based on the code logic. For details, see Kunpeng Math Library Developer Guide in Kunpeng HPCKit 26.1.RC1 Developer Guide.

Table 1 shows the mapping between replaceable interfaces and MKL interfaces.

Table 1 FFT replacement mapping

MKL Interface

KML Interface

Description

DftiCreateDescriptor

DftiSetValue

DftiCommitDescriptor

kml_fft_plan_dft

kml_fft_plan_dft_1d

kml_fft_plan_dft_2d

kml_fft_plan_dft_3d

kml_fft_plan_dft_c2r

kml_fft_plan_dft_c2r_1d

kml_fft_plan_dft_c2r_2d

kml_fft_plan_dft_c2r_3d

kml_fft_plan_dft_r2c

kml_fft_plan_dft_r2c_1d

kml_fft_plan_dft_r2c_2d

kml_fft_plan_dft_r2c_3d

kml_fft_plan_guru64_dft

kml_fft_plan_guru64_dft_c2r

kml_fft_plan_guru64_dft_r2c

kml_fft_plan_guru64_r2r

kml_fft_plan_guru64_split_dft

kml_fft_plan_guru64_split_dft_c2r

kml_fft_plan_guru64_split_dft_r2c

kml_fft_plan_guru_dft

kml_fft_plan_guru_dft_c2r

kml_fft_plan_guru_dft_r2c

kml_fft_plan_guru_r2r

kml_fft_plan_guru_split_dft

kml_fft_plan_guru_split_dft_c2r

kml_fft_plan_guru_split_dft_r2c

kml_fft_plan_many_dft

kml_fft_plan_many_dft_c2r

kml_fft_plan_many_dft_r2c

kml_fft_plan_many_r2r

kml_fft_plan_r2r

kml_fft_plan_r2r_1d

kml_fft_plan_r2r_2d

kml_fft_plan_r2r_3d

kml_fft_plan_with_nthreads

kml_fft_init_threads

kml_fft_cleanup_threads

MKL builds an FFT model in three steps:

  1. Call DftiCreateDescriptor to create a descriptor.
  2. Call DftiSetValue to set parameters.
  3. Call DftiCommitDescriptor to complete the creation.

KML uses different plan interfaces based on the problem type. Different plan interfaces require different parameter configurations, which are transferred to plan interfaces through parameters. You need to replace them separately during the migration.

For details, see the three code samples provided in Migrating the C-based Library.

DftiFreeDescriptor

kml_fft_destroy_plan

kml_fft_free

This interface is used to release resources associated with a model.

DftiCopyDescriptor

N/A

-

DftiComputeForward

kml_fft_execute

kml_fft_execute_dft

kml_fft_execute_split_dft

kml_fft_execute_dft_r2c

kml_fft_execute_split_dft_r2c

DftiComputeForward is used for the C2C and R2C problems in MKL, while the execution functions related to C2C and R2C in KML are used.

DftiComputeBackward

kml_fft_execute

kml_fft_execute_dft

kml_fft_execute_split_dft

kml_fft_execute_dft_c2r

kml_fft_execute_split_dft_c2r

DftiComputeBackward is used for the C2C and C2R problems in MKL while the execution functions related to C2C and C2R in KML are used.

DftiGetValue

N/A

-

DftiErrorClass

N/A

-

DftiErrorMessage

N/A

-

Migrating the C-based Library

  • Example: C2C transform
    Before the migration:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    #include "mkl_cdft.h"
    #include "mkl_cdft_types.h"
    
        DFTI_DESCRIPTOR_HANDLE desc_handle = NULL;
        MKL_LONG rank = 2;
        MKL_LONG length[2] = {2, 3};
        MKL_LONG istrides[3] = {0, 3, 1};
        MKL_LONG ostrides[3] = {0, 3, 1};
        MKL_LONG nthreads = 1;
        MKL_LONG howmany = 2;
        MKL_LONG idistance = 2 * 3;
        MKL_LONG odistance = 2 * 3;
        double init[12][2] = {{120, 0}, {8, 8}, {0, 0}, {0, 16}, {0, 16}, {-8, 8}, {-8, 0}, {-8, 8}, {-16, 0}, {0, -16}, {-40, 8}, {-8, -8}};
        double *ri;
        ri = (double*)malloc(sizeof(double) * 12);
        double *ii;
        ii = (double*)malloc(sizeof(double) * 12);
        for (int i = 0; i < 12; i++) {
            ri[i] = init[i][0];
            ii[i] = init[i][1];
        }
    
        MKL_LONG s = DftiCreateDescriptor(&desc_handle, DFTI_DOUBLE, DFTI_COMPLEX, rank, length);
        s = DftiSetValue(desc_handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
        s = DftiSetValue(desc_handle, DFTI_INPUT_STRIDES, istrides);
        s = DftiSetValue(desc_handle, DFTI_OUTPUT_STRIDES, ostrides);
        s = DftiSetValue(desc_handle, DFTI_THREAD_LIMIT, nthreads);
        s = DftiSetValue(desc_handle, DFTI_COMPLEX_STORAGE, DFTI_REAL_REAL);
        s = DftiSetValue(desc_handle, DFTI_NUMBER_OF_TRANSFORMS, howmany);
        s = DftiSetValue(desc_handle, DFTI_INPUT_DISTANCE, idistance);
        s = DftiSetValue(desc_handle, DFTI_OUTPUT_DISTANCE, odistance);
        s = DftiCommitDescriptor(desc_handle);
        double *ro;
        ro = (double*)malloc(sizeof(double) * 12);
        double *io;
        io = (double*)malloc(sizeof(double) * 12);
        DftiComputeForward(desc_handle, ri, ii, ro, io);
        DftiFreeDescriptor(&desc_handle);
        free(ri);
        free(ii);
        free(ro);
        free(io);
    
    After the migration:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #include "kfft.h"
    
        int rank = 2; 
        kml_fft_iodim64 *dims; 
        dims = (kml_fft_iodim64*)kml_fft_malloc(sizeof(kml_fft_iodim64) * rank); 
        dims[0].n = 2; 
        dims[0].is = 3; 
        dims[0].os = 3; 
        dims[1].n = 3; 
        dims[1].is = 1; 
        dims[1].os = 1; 
        int howmany_rank = 1; 
        kml_fft_iodim64 *howmany_dims; 
        howmany_dims = (kml_fft_iodim64*)kml_fft_malloc(sizeof(kml_fft_iodim64) * howmany_rank); 
        howmany_dims[0].n = 2; 
        howmany_dims[0].is = 2 * 3; 
        howmany_dims[0].os = 2 * 3; 
        double init[12][2] = {{120, 0}, {8, 8}, {0, 0}, {0, 16}, {0, 16}, {-8, 8}, {-8, 0}, {-8, 8}, {-16, 0}, {0, -16}, {-40, 8}, {-8, -8}}; 
        double *ri; 
        ri = (double*)kml_fft_malloc(sizeof(double) * 12); 
        double *ii; 
        ii = (double*)kml_fft_malloc(sizeof(double) * 12); 
        for (int i = 0; i < 12; i++) { 
            ri[i] = init[i][0]; 
            ii[i] = init[i][1]; 
        } 
        double *ro; 
        ro = (double*)kml_fft_malloc(sizeof(double) * 12); 
        double *io; 
        io = (double*)kml_fft_malloc(sizeof(double) * 12); 
        kml_fft_plan plan; 
        plan = kml_fft_plan_guru64_split_dft(rank, dims, howmany_rank, howmany_dims, ri, ii, ro, io, KML_FFT_ESTIMATE); 
        kml_fft_execute_split_dft(plan, ri, ii, ro, io); 
     
        kml_fft_destroy_plan(plan); 
        kml_fft_free(howmany_dims); 
        kml_fft_free(dims); 
        kml_fft_free(ri); 
        kml_fft_free(ii); 
        kml_fft_free(ro); 
        kml_fft_free(io); 
     
        /* 
         * ro = {1.200000e+02, 1.338564e+02, 1.061436e+02, 1.360000e+02, 
         *       1.120000e+02, 1.120000e+02, -8.000000e+01, 4.878461e+01, 
         *       7.215390e+00, 1.600000e+01, -2.692820e+01, -1.307180e+01} 
         */ 
     
        /* 
         * io = {4.800000e+01, -1.385641e+01, 1.385641e+01, -3.200000e+01, 
         *       -8.000000e+00, -8.000000e+00, -8.000000e+00, 7.846097e-01, 
         *       -4.078461e+01, 2.400000e+01, -2.264102e+01, 4.664102e+01} 
         */
    
  • Example: R2C transform
    Before the migration:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include "mkl_cdft.h"
    #include "mkl_cdft_types.h"
    
        DFTI_DESCRIPTOR_HANDLE desc_handle = NULL;
        MKL_LONG rank = 2;
        MKL_LONG length[2] = {2, 3};
        MKL_LONG istrides[3] = {0, 3, 1};
        MKL_LONG ostrides[3] = {0, 2, 1};
        MKL_LONG nthreads = 1;
        MKL_LONG howmany = 2;
        MKL_LONG idistance = 2 * 3;
        MKL_LONG odistance = 2 * 2;
        double init[12] = {120, 8, 0, 0, 0, -8, -8, -8, -16, 0, -40, -8};
        double *in;
        in = (double*)malloc(sizeof(double) * 12);
        for (int i = 0; i < 12; i++) {
            in[i] = init[i];
        }
    
        MKL_LONG s = DftiCreateDescriptor(&desc_handle, DFTI_DOUBLE, DFTI_REAL, rank, length);
        s = DftiSetValue(desc_handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
        s = DftiSetValue(desc_handle, DFTI_INPUT_STRIDES, istrides);
        s = DftiSetValue(desc_handle, DFTI_OUTPUT_STRIDES, ostrides);
        s = DftiSetValue(desc_handle, DFTI_THREAD_LIMIT, nthreads);
        s = DftiSetValue(desc_handle, DFTI_COMPLEX_STORAGE, DFTI_COMPLEX_COMPLEX);
        s = DftiSetValue(desc_handle, DFTI_NUMBER_OF_TRANSFORMS, howmany);
        s = DftiSetValue(desc_handle, DFTI_INPUT_DISTANCE, idistance);
        s = DftiSetValue(desc_handle, DFTI_OUTPUT_DISTANCE, odistance);
        s = DftiSetValue(desc_handle, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
        s = DftiCommitDescriptor(desc_handle);
    
        MKL_Complex16 *out;
        out = (MKL_Complex16*)malloc(sizeof(MKL_Complex16) * 2 * 2 * howmany);
        DftiComputeForward(desc_handle, in, out);
        DftiFreeDescriptor(&desc_handle);
        free(in);
        free(out);
    
    After the migration:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include "kfft.h"
    
        int rank = 2; 
        kml_fft_iodim64 *dims; 
        dims = (kml_fft_iodim64*)kml_fft_malloc(sizeof(kml_fft_iodim64) * rank); 
        dims[0].n = 2; 
        dims[0].is = 3; 
        dims[0].os = 2; 
        dims[1].n = 3; 
        dims[1].is = 1; 
        dims[1].os = 1; 
        int howmany_rank = 1; 
        kml_fft_iodim64 *howmany_dims; 
        howmany_dims = (kml_fft_iodim64*)kml_fft_malloc(sizeof(kml_fft_iodim64) * howmany_rank); 
        howmany_dims[0].n = 2; 
        howmany_dims[0].is = 2 * 3; 
        howmany_dims[0].os = 2 * 2; 
        double init[12] = {120, 8, 0, 0, 0, -8, -8, -8, -16, 0, -40, -8}; 
        double *in; 
        in = (double*)kml_fft_malloc(sizeof(double) * 12); 
        for (int i = 0; i < 12; i++) { 
            in[i] = init[i]; 
        } 
        kml_fft_complex *out; 
        out = (kml_fft_complex*)kml_fft_malloc(sizeof(kml_fft_complex) * 8); 
        kml_fft_plan plan; 
        plan = kml_fft_plan_guru64_dft_r2c(rank, dims, howmany_rank, howmany_dims, in, out, KML_FFT_ESTIMATE); 
        kml_fft_execute_dft_r2c(plan, in, out); 
     
        kml_fft_destroy_plan(plan); 
        kml_fft_free(howmany_dims); 
        kml_fft_free(dims); 
        kml_fft_free(in); 
        kml_fft_free(out); 
     
        /* 
         * out = {{1.200000e+02, 0.000000e+00}, {1.200000e+02, -1.385641e+01}, 
         *        {1.360000e+02, 0.000000e+00}, {1.120000e+02, 0.000000e+00}, 
         *        {-8.000000e+01, 0.000000e+00}, {2.800000e+01, 2.078461e+01}, 
         *        {1.600000e+01, 0.000000e+00}, {-2.000000e+01, -3.464102e+01}} 
         */
    
  • Example: C2R transform
    Before the migration:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #include "mkl_cdft.h"
    #include "mkl_cdft_types.h"
    
        DFTI_DESCRIPTOR_HANDLE desc_handle = NULL;
        MKL_LONG rank = 2;
        MKL_LONG length[2] = {2, 3};
        MKL_LONG istrides[3] = {0, 2, 1};
        MKL_LONG ostrides[3] = {0, 3, 1};
        MKL_LONG nthreads = 1;
        MKL_LONG howmany = 2;
        MKL_LONG idistance = 2 * 2;
        MKL_LONG odistance = 2 * 3;
        double init[8][2] = {{120, 0}, {8, 8}, {0, 0}, {0, 16}, {0, 16}, {-8, 8}, {-8, 0}, {-8, 8}}; 
        MKL_Complex16 *in; 
        in = (MKL_Complex16*)malloc(sizeof(MKL_Complex16) * 8); 
        for (int i = 0; i < 8; i++) { 
            in[i].real = init[i][0]; 
            in[i].imag = init[i][1];
        } 
    
        MKL_LONG s = DftiCreateDescriptor(&desc_handle, DFTI_DOUBLE, DFTI_REAL, rank, length);
        s = DftiSetValue(desc_handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
        s = DftiSetValue(desc_handle, DFTI_INPUT_STRIDES, istrides);
        s = DftiSetValue(desc_handle, DFTI_OUTPUT_STRIDES, ostrides);
        s = DftiSetValue(desc_handle, DFTI_THREAD_LIMIT, nthreads);
        s = DftiSetValue(desc_handle, DFTI_COMPLEX_STORAGE, DFTI_COMPLEX_COMPLEX);
        s = DftiSetValue(desc_handle, DFTI_NUMBER_OF_TRANSFORMS, howmany);
        s = DftiSetValue(desc_handle, DFTI_INPUT_DISTANCE, idistance);
        s = DftiSetValue(desc_handle, DFTI_OUTPUT_DISTANCE, odistance);
        s = DftiSetValue(desc_handle, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
        s = DftiCommitDescriptor(desc_handle);
    
        double *out; 
        out = (double*)malloc(sizeof(double) * 12);
        DftiComputeBackward(desc_handle, in, out);
        DftiFreeDescriptor(&desc_handle);
        free(in);
        free(out);
    
    After the migration:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include "kfft.h"
    
        int rank = 2; 
        kml_fft_iodim64 *dims; 
        dims = (kml_fft_iodim64*)kml_fft_malloc(sizeof(kml_fft_iodim64) * rank); 
        dims[0].n = 2; 
        dims[0].is = 2; 
        dims[0].os = 3; 
        dims[1].n = 3; 
        dims[1].is = 1; 
        dims[1].os = 1; 
        int howmany_rank = 1; 
        kml_fft_iodim64 *howmany_dims; 
        howmany_dims = (kml_fft_iodim64*)kml_fft_malloc(sizeof(kml_fft_iodim64) * howmany_rank); 
        howmany_dims[0].n = 2; 
        howmany_dims[0].is = 2 * 2; 
        howmany_dims[0].os = 2 * 3; 
        double init[8][2] = {{120, 0}, {8, 8}, {0, 0}, {0, 16}, {0, 16}, {-8, 8}, {-8, 0}, {-8, 8}}; 
        kml_fft_complex *in; 
        in = (kml_fft_complex*)kml_fft_malloc(sizeof(kml_fft_complex) * 8); 
        for (int i = 0; i < 8; i++) { 
            in[i].r = init[i][0]; 
            in[i].i = init[i][1]; 
        }
        double *out; 
        out = (double*)kml_fft_malloc(sizeof(double) * 12); 
        kml_fft_plan plan; 
        plan = kml_fft_plan_guru64_dft_c2r(rank, dims, howmany_rank, howmany_dims, in, out, KML_FFT_ESTIMATE); 
        kml_fft_execute_dft_c2r(plan, in, out); 
     
        kml_fft_destroy_plan(plan); 
        kml_fft_free(howmany_dims); 
        kml_fft_free(dims); 
        kml_fft_free(in); 
        kml_fft_free(out); 
     
        /* 
         * out = {1.360000e+02, 7.043078e+01, 1.535692e+02, 1.360000e+02, 
         *        1.258564e+02, 9.814359e+01, -4.000000e+01, -1.971281e+01, 
         *        3.571281e+01, 8.000000e+00, 8.000000e+00, 8.000000e+00} 
         */
    

    Due to the software architecture, different plans are required for calculating different types of Fourier transforms for multiple times in the service code. Similar to MKL, a plan constructed based on the same type of transform can be used for multiple times.

Migrating the Fortran-based Library

See Migrating the C-based Library.