我在使用fftw
库执行FFT计划时遇到问题。我正在声明大小为2048的fftIn
和fftOut
向量,并使用它们定义fftwf_plan_dft_1d
。
但是当我执行计划时,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都在同一个线程中发生,因此竞争条件不应该适用),这是尝试在这个小例子中隔离代码的原因之一,以防万一,但它好像无论如何都有问题。
有什么想法吗?
答案 0 :(得分:3)
主要问题是你传递了一个矢量,它不会起作用;你需要传递矢量内容:&amp;((* fftIn)[0])和&amp;((* 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 ++ complex和vector,这应该有效:
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提供的地址(指针)。
答案 1 :(得分: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);