2014-12-06 127 views
2

我想計算3D FFT使用Intel MKL的數組,其具有300×200×200元素。這種3D數組存儲爲double類型的縱列方式一維數組:使用帶有零填充的英特爾MKL的3D FFT

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; 
} 

回答

0

只是一些提示:

電源的2
  1. 大小

    • 我不喜歡你正在計算大小的方式
    • 所以讓Nx,Ny,Nz是大小輸入矩陣
    • nx,ny,nz填充矩陣的大小IX

      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完成
    • 如果由線做......看到這2D DFCT by 1D DFFT在3D
    • 是相同的,但你需要添加一個通和不同的歸一化常數
    • 這種方式,您可以有單行緩衝double lin[2*max(nx,ny,nz)];
    • ,並就運行(這樣就無需在內存中擁有更大的矩陣)零填充...
    • 但涉及應對上線每個1D DFFT ...