簡體   English   中英

使用具有零填充的Intel MKL進行3D FFT

[英]3D FFT Using Intel MKL with Zero Padding

我想使用具有 300×200×200元素的陣列的Intel MKL計算3D FFT 此3D數組以列方式存儲為double類型的1D數組:

for( int k = 0; k < nk; k++ ) // Loop through the height.
    for( int j = 0; j < nj; j++ ) // Loop through the rows.
        for( int i = 0; i < ni; i++ ) // Loop through the columns.
        {
            ijk = i + ni * j + ni * nj * k;
            my3Darray[ ijk ] = 1.0;
        }

我想在輸入數組上執行not-in-place FFT並防止其被修改(我稍后需要在我的代碼中使用它),然后進行in-place反向計算。 我也想有零填充。

我的問題是:

  1. 如何執行零填充?
  2. 當計算中包括零填充時,應如何處理FFT函數使用的數組的大小?
  3. 如何取出零填充結果並獲得實際結果?

這是我對問題的嘗試,對於任何評論,建議或暗示,我將深表感謝

#include <stdio.h>
#include "mkl.h"

int max(int a, int b, int c)
{
     int m = a;
     (m < b) && (m = b); 
     (m < c) && (m = c); 
     return m;
}

void FFT3D_R2C( // Real to Complex 3D FFT.
    double *in, int nRowsIn , int nColsIn , int nHeightsIn ,
    double *out )
{    
    int n  = max( nRowsIn , nColsIn , nHeightsIn  );
    // Round up to the next highest power of 2.
    unsigned int N = (unsigned int) n; // compute the next highest power of 2 of 32-bit n.
    N--;
    N |= N >> 1;
    N |= N >> 2;
    N |= N >> 4;
    N |= N >> 8;
    N |= N >> 16;
    N++;

    /* Strides describe data layout in real and conjugate-even domain. */
    MKL_LONG rs[4], cs[4];

    // DFTI descriptor.
    DFTI_DESCRIPTOR_HANDLE fft_desc = 0;

    // Variables needed for out-of-place computations.
    MKL_Complex16 *in_fft  = new MKL_Complex16 [ N*N*N ];
    MKL_Complex16 *out_fft = new MKL_Complex16 [ N*N*N ];
    double *out_ZeroPadded = new double [ N*N*N ];

    /* Compute strides */
    rs[3] = 1;           cs[3] = 1;
    rs[2] = (N/2+1)*2;   cs[2] = (N/2+1);
    rs[1] = N*(N/2+1)*2; cs[1] = N*(N/2+1);
    rs[0] = 0;           cs[0] = 0;

    // Create DFTI descriptor.
    MKL_LONG sizes[] = { N, N, N };
    DftiCreateDescriptor( &fft_desc, DFTI_DOUBLE, DFTI_REAL, 3, sizes );

    // Configure DFTI descriptor.
    DftiSetValue( fft_desc, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX );
    DftiSetValue( fft_desc, DFTI_PLACEMENT, DFTI_NOT_INPLACE  ); // Out-of-place transformation.
    DftiSetValue( fft_desc, DFTI_INPUT_STRIDES  , rs  );
    DftiSetValue( fft_desc, DFTI_OUTPUT_STRIDES , cs  );

    DftiCommitDescriptor( fft_desc );
    DftiComputeForward  ( fft_desc, in , in_fft  );

    // Change strides to compute backward transform.
    DftiSetValue        ( fft_desc, DFTI_INPUT_STRIDES , cs);
    DftiSetValue        ( fft_desc, DFTI_OUTPUT_STRIDES, rs);
    DftiCommitDescriptor( fft_desc );
    DftiComputeBackward ( fft_desc, out_fft, out_ZeroPadded );

    // Printing the zero padded 3D FFT result.
    for( long long i = 0; i < (long long)N*N*N; i++ )
        printf("%f\n", out_ZeroPadded[i] );

    /* I don't know how to take out the zero padded results and 
       save the actual result in the variable named "out" */

    DftiFreeDescriptor  ( &fft_desc );

    delete[] in_fft;
    delete[] out_ZeroPadded ;
}

int main()
{
    int n = 10;

    double *a    = new double [n*n*n]; // This array is real.
    double *afft = new double [n*n*n]; 

    // Fill the array with some 'real' numbers.
    for( int i = 0; i < n*n*n; i++ )
        a[ i ] = 1.0;

    // Calculate FFT.
    FFT3D_R2C( a, n, n, n, afft );

    printf("FFT results:\n");
    for( int i = 0; i < n*n*n; i++ )
        printf( "%15.8f\n", afft[i] );

    delete[] a;
    delete[] afft;

    return 0;
}

只是一些提示:

  1. 2大小的力量

    • 我不喜歡您計算尺寸的方式
    • 所以令Nx,Ny,Nz為輸入矩陣的大小
    • nx,ny,nz填充矩陣的大小

       for (nx=1;nx<Nx;nx<<=1); for (ny=1;ny<Ny;ny<<=1); for (nz=1;nz<Nz;nz<<=1); 
    • 現在通過memset將零填充首先設置為零,然后復制矩陣線

    • 填充到N^3而不是nx*ny*nz可能會導致大幅降低
    • 如果nx,ny,nz不彼此靠近
  2. 輸出復雜

    • 如果我做對a則輸入實矩陣
    • afft輸出復雜矩陣
    • 那為什么不正確分配空間呢?
    • double *afft = new double [2*nx*ny*nz];
    • 復數是實數+虛數部分,所以每個數2個值
    • 這也用於最終打印結果
    • 和一些"\\r\\n"行后將是很好的查看
  3. 3D DFFT

    • 我不使用也不知道您的DFFT庫
    • 我使用自己的,但是無論如何3D DFFT可以通過1D DFFT完成
    • 如果您按行執行...請參閱此1D DFFT的2D DFCT
    • 在3D中是相同的,但是您需要添加一遍和不同的歸一化常數
    • 這樣,您可以擁有單行緩沖區double lin[2*max(nx,ny,nz)];
    • 並在運行中進行零填充(因此無需在內存中使用更大的矩陣)...
    • 但這涉及應對每個1D DFFT上的線...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM