2016-11-29 8 views
0

fftwライブラリでFFTプランを実行する際に問題があります。私はfftInfftOutのサイズ2048のベクトルを宣言し、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は2番目のcoutで発生します。

私のフルコードにはスレッドがあります(ただし、FFTはすべて同じスレッド内で発生するため、競合条件は適用しないでください)、この小さな例でコードを分離しようとした理由の1つですそれはとにかく何かが間違っているようです。

答えて

3

主な問題は、あなたが動作しませんこれは、それにベクトルを渡しているということです。ベクトルコンテンツ:&((* fftIn)[0])と&((* fftOut)[0])を渡す必要があります。それは、fftwにベクトルオブジェクトのメタデータ(長さを含む)を押し付けるように伝えているのです。長さは時々0であり、時にはぎこちないものであるという理由が説明されています。文字通りベクトル構造の先頭に書いていたのは、ポインタが指しているものなのです。また、fftInのメタデータをfftへの入力の一部として使用していました。これはあなたが望むものでもありません。

あなたはFFTWが必要な方法整列してデータが格納されていることを保証しますこれは、代わりにfftw_complexとfftw_mallocを使用して検討するかもしれない:あなたは本当にそれが必要な場合は、その後、ベクターでfftOutを置くことができるhttp://www.fftw.org/doc/SIMD-alignment-and-fftw_005fmalloc.html を。これにより、可能であれば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); 
} 

は、この例に一致するようにしてみて、あなたのコードは、あなたが期待する何をすべき。

EDIT: あなたが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++のcomplex <>型が動作することは保証されていないかもしれません。 – Andrew

+0

好奇心が強い:C++の複雑な<>で可能な場合、コードをどのように書き直すべきですか?動的なベクトルとして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); 
関連する問題