简体   繁体   English

执行FFT计划后FFTW输出向量大小错误

[英]FFTW output vector size is wrong after executing the FFT plan

I am having trouble executing an FFT plan with fftw library. 我在使用fftw库执行FFT计划时遇到麻烦。 I am declaring fftIn and fftOut vectors with size 2048, and defining a fftwf_plan_dft_1d with them. 我要声明大小为2048的fftInfftOut向量,并使用它们定义fftwf_plan_dft_1d

But when I execute the plan, suddenly the fftOut vector gets all wrong. 但是,当我执行该计划时,突然fftOut向量完全错误。 In my code, I can see while debugging that its size goes from 2048 to 0. When I wrote the small executable example below, I just get bad sizes such as 17293858104588369909. 在我的代码中,我在调试时可以看到它的大小从2048变为0。当我编写下面的小型可执行示例时,我得到的大小很不好,例如17293858104588369909。

Of course, when I try to access to the first item of the vector, a SIGSEGV happens. 当然,当我尝试访问向量的第一项时,会发生SIGSEGV

My code: 我的代码:

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

Of course, I know fftIn vector is empty in this example, but output is broken when it is not anyway. 当然,在此示例中,我知道fftIn向量为空,但无论如何都不输出。 In this case, the SIGSEGV happens in the second cout as described before. 在这种情况下,SIGSEGV如前所述发生在第二个洞中。

My full code has threads (but FFT happens all within the same thread, so race conditions should not apply), and that was one of the reasons for trying to isolate the code in this small example, just in case, but it seems to have something wrong anyway. 我的完整代码具有线程(但是FFT都发生在同一线程中,因此竞争条件不适用),这是在这个小示例中尝试隔离代码的原因之一,以防万一,但似乎有反正有什么问题。

Any idea? 任何想法?

The main issue is that you are passing a vector to it, which won't work; 主要问题是您正在向其传递向量,这是行不通的。 you need to pass the vector contents: &((*fftIn)[0]) and &((*fftOut)[0]) or something comparable. 您需要传递矢量内容:&((** fftIn)[0])和&((** fftOut)[0])或类似的东西。 As it is, you are telling fftw to stomp on the vector object's metadata (including the length, which explains why it was sometimes 0 and sometimes gibberish). 照原样,您正在告诉fftw踩矢量对象的元数据(包括长度,这解释了为什么有时为0有时为乱码)。 It was literally writing to the start of the vector structure because that's what the pointer points to. 它实际上是在写向量结构的开头,因为这就是指针所指向的。 Also it was using fftIn's metadata as part of the input to the fft, which is also not what you want. 同样,它使用fftIn的元数据作为fft输入的一部分,这也不是您想要的。

You might consider using fftw_complex and fftw_malloc instead, which will ensure that your data is stored aligned the way fftw needs: http://www.fftw.org/doc/SIMD-alignment-and-fftw_005fmalloc.html You can put fftOut in a vector afterwards if you really need it. 您可以考虑改用fftw_complex和fftw_malloc,这将确保您的数据按照fftw所需的方式存储: http ://www.fftw.org/doc/SIMD-alignment-and-fftw_005fmalloc.html您可以将fftOut放在之后,如果您真的需要它。 This will ensure that you get the advantages of SIMD, if available, and avoid any compiler- or platform-specific behavior with complex types and memory allocation. 这将确保您获得SIMD的优势(如果有),并避免使用复杂类型和内存分配的任何特定于编译器或平台的行为。 Using fftw's type and allocator means your code will always work optimally and as you expect, regardless of which platform you run it on and which compiler you use. 使用fftw的类型和分配器意味着您的代码将始终以最佳状态运行,并且符合您的期望,无论您在哪个平台上运行它以及使用哪个编译器。

Here is an example of your transform from fftw's documentation ( http://www.fftw.org/doc/Complex-One_002dDimensional-DFTs.html ): 这是您从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);
}

Try to match this example and your code should do what you expect. 尝试匹配此示例,您的代码应达到预期的效果。

EDIT: If you must use C++ complex and vector, this should work: 编辑:如果您必须使用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;

Notice that you have to dereference the vector pointer in order to get the [] operator to work; 注意,必须取消引用向量指针才能使[]运算符起作用。 getting index 0 gives you the first element of the actual vector data and so the address of that element is the address (pointer) you need to give to fftw_plan. 获得索引0将为您提供实际矢量数据的第一个元素,因此该元素的地址就是您需要赋予fftw_plan的地址(指针)。

you cannot reinterpret_cast a vector to a pointer on complex elements: you're accessing the vector inner variables (like the size), not necessarily the vector raw data, which probably explains why the object is trashed in output, and all the bad things that happen next. 您不能reinterpret_cast向量reinterpret_cast为复杂元素上的指针:您正在访问向量内部变量(例如大小),不一定是向量原始数据,这很可能解释了为什么对象被丢弃在输出中以及所有的不良情况接下来发生。

On the other hand, casting the address of the vector data works. 另一方面,投射矢量数据的地址是可行的。

Just do (no need to new the vectors too, use standard declaration): 只需做即可(也无需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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM