2016-11-29 54 views
0

我在執行FFT計劃時出現問題,因爲它存在fftw庫。我聲明瞭尺寸爲2048的fftInfftOut向量,並定義了它們的fftwf_plan_dft_1d執行FFT計劃後,FFTW輸出矢量大小錯誤

但是,當我執行計劃,突然fftOut矢量得到完全錯誤的。在我的代碼中,我可以在調試時看到它的大小從2048變爲0.當我編寫下面的小可執行示例時,我只是得到不合適的大小,例如17293858104588369909.

當然,當我嘗試訪問向量的第一項,發生SIGSEGV

我的代碼:

#include <complex> 
#include <iostream> 
#include <fftw3.h> 
#include <vector> 
using namespace std; 

typedef std::vector<std::complex<float>> fft_vector; 

int main() { 
    const unsigned int VECTOR_SIZE = 2048; 
    fft_vector* fftIn = new fft_vector(VECTOR_SIZE); 
    fft_vector* fftOut = new fft_vector(VECTOR_SIZE); 

    fftwf_plan fftPlan = fftwf_plan_dft_1d(VECTOR_SIZE, reinterpret_cast<fftwf_complex*>(fftIn), reinterpret_cast<fftwf_complex*>(fftOut), FFTW_FORWARD, FFTW_ESTIMATE); 

    fftwf_execute(fftPlan); 

    std::cout << fftOut->size() << std::endl; 
    std::cout << fftOut->at(0).real() << fftOut->at(0).imag() << std::endl; 

    return 0; 
} 

當然,我知道fftIn向量是空在這個例子中,但輸出被打破時,它不是無妨。在這種情況下,SIGSEGV發生在第二個cout中,如前所述。

我的完整代碼有線程(但FFT發生在同一個線程中,所以競爭條件不應該適用),這是試圖在這個小例子中隔離代碼的原因之一,以防萬一,但無論如何,它似乎有什麼問題。

有什麼想法?

回答

3

的主要問題是要傳遞一個向量給它,這將無法正常工作;您需要傳遞向量內容:&((* fftIn)[0])和&((* fftOut)[0])或類似的東西。實際上,您正在告訴fftw踩到矢量對象的元數據(包括長度,這就解釋了爲什麼它有時是0,有時候是亂碼)。它實際上是寫入向量結構的開始,因爲這是指針指向的內容。另外它使用fftIn的元數據作爲fft輸入的一部分,這也不是你想要的。

您可以考慮使用fftw_complex和fftw_malloc代替,這將確保您的數據存儲的對齊方式FFTW需求:http://www.fftw.org/doc/SIMD-alignment-and-fftw_005fmalloc.html 你可以把fftOut在矢量之後,如果你真的需要它。這將確保您獲得SIMD的優勢(如果可用),並避免使用複雜類型和內存分配的任何編譯器或平臺特定的行爲。使用fftw的類型和分配器意味着您的代碼將始終以最佳方式正常工作,並且與您期望的一樣,無論您在哪個平臺上運行它以及使用哪種編譯器。

下面是從FFTW的文檔(http://www.fftw.org/doc/Complex-One_002dDimensional-DFTs.html)您的變換的例子:

#include <fftw3.h> 
... 
{ 
    fftw_complex *in, *out; 
    fftw_plan p; 
    ... 
    in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); 
    out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); 
    p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE); 
    ... 
    fftw_execute(p); /* repeat as needed */ 
    ... 
    fftw_destroy_plan(p); 
    fftw_free(in); fftw_free(out); 
} 

嘗試匹配這個例子中,你的代碼應該做你的期望。

編輯: 如果必須使用C++複雜和載體,這應該工作:

const unsigned int VECTOR_SIZE = 2048; 
fft_vector* fftIn = new fft_vector(VECTOR_SIZE); 
fft_vector* fftOut = new fft_vector(VECTOR_SIZE); 

fftwf_plan fftPlan = fftwf_plan_dft_1d(VECTOR_SIZE, 
    reinterpret_cast<fftwf_complex*>(&(*fftIn)[0]), 
    reinterpret_cast<fftwf_complex*>(&(*fftOut)[0]), 
    FFTW_FORWARD, FFTW_ESTIMATE); 

fftwf_execute(fftPlan); 

std::cout << fftOut->size() << std::endl; 
std::cout << fftOut->at(0).real() << fftOut->at(0).imag() << std::endl; 

請注意,您必須取消引用矢量指針,以獲得[]操作工作;獲取索引0會爲您提供實際向量數據的第一個元素,因此該元素的地址是您需要爲fftw_plan提供的地址(指針)。

+0

它應該工作:http://www.fftw.org/doc/Complex-numbers.html#Complex-numbers無論如何,我會嘗試你建議的經典代碼 –

+1

@RomanRdgz是的,它應該。主要問題是你傳遞的是矢量而不是矢量的內容。使用fftw的類型和分配是額外的保險,您可以從fftw中獲得您想要的行爲和表現。還要注意在該鏈接中使用「should」這個詞:它可能無法保證(至少對所有平臺上的所有編譯器)C++複雜<>類型可以工作。 – Andrew

+0

只是好奇:如果可能用C++ complex <>來做,我應該如何重寫代碼?保持fftIn和fftOut爲動態矢量,因爲我需要它們的大小是可配置的。另一方面,我不清楚如何訪問輸出矢量內容。 (&fftOut [0])。x? –

1

您不能reinterpret_cast向量指向複雜元素的指針:您正在訪問矢量內部變量(如大小),不一定是矢量原始數據,這可能解釋了爲什麼該對象在輸出中被丟棄,以及所有接下來發生的壞事。

另一方面,投射矢量數據的地址起作用。

只是做(無需new向量太,使用標準的聲明):

fft_vector fftIn(VECTOR_SIZE); 
fft_vector fftOut(VECTOR_SIZE); 
// load your data in fftIn 
fftwf_plan_dft_1d(VECTOR_SIZE, static_cast<const fftwf_complex*>(&fftIn[0]), static_cast<fftwf_complex*>(&fftOut[0]), FFTW_FORWARD, FFTW_ESTIMATE);