C++ 使用std::vector容器进行FFT时FFTW3分割错误

C++ 使用std::vector容器进行FFT时FFTW3分割错误,c++,segmentation-fault,allocation,fftw,C++,Segmentation Fault,Allocation,Fftw,我想征求您关于在执行FFT时使用std::vector容器的建议 在我的程序中,我在循环中使用某个函数(get\u PDF\u CDF)。当我使用std::vector容器执行FFT时,在某个迭代(通常是第二个迭代)期间,我得到了一个分段错误/内存损坏错误 我知道FFTW最好使用FFTW_malloc和FFTW_free提供的对齐方式,但我想在整个程序中增加一些内容并一致地使用std::vector 我已经重写了这个函数,使用了推荐的分配例程——它本质上是将向量的内容复制到使用fftw例程分配和

我想征求您关于在执行FFT时使用std::vector容器的建议

在我的程序中,我在循环中使用某个函数(get\u PDF\u CDF)。当我使用std::vector容器执行FFT时,在某个迭代(通常是第二个迭代)期间,我得到了一个分段错误/内存损坏错误

我知道FFTW最好使用FFTW_malloc和FFTW_free提供的对齐方式,但我想在整个程序中增加一些内容并一致地使用std::vector

我已经重写了这个函数,使用了推荐的分配例程——它本质上是将向量的内容复制到使用fftw例程分配和释放的浮点数组中——它工作得很好,但仍然存在问题。它还涉及对高斯滤波器和顶帽滤波器的简单重写。此外,我想了解我是否可以用std::vectors以任何方式修改版本,使其不会产生分段错误

下面是两个版本,截短为其基本内容。如果这不足以进行错误跟踪,我深表歉意-在这种情况下,我将提供一个工作示例,尽管从代码中提取可能需要一些时间

FFTW分配例程版本:

void get_PDF_CDF(float rbin, std::string filtertype, std::vector<float> field,
                std::vector<float>& PDF_x, std::vector<int>& PDF_counts, 
   std::vector<float>& PDF, std::vector<float>& CDF){

/*===========================================================
Here we go to Fourier space for applying smoothing filters
=============================================================*/
#ifdef smoothing_filters

fftwf_complex * Fourierfield;
float * field_to_fourier;
Fourierfield = (fftwf_complex*) fftwf_malloc(pow(NGRID,2)*(NGRID/2 + 1)*sizeof(fftwf_complex));
field_to_fourier = (float*) fftwf_malloc(pow(NGRID,3)*sizeof(float));

std::cout << "The FFTW multi-threaded calculations are " << (fftw_init_threads() ? "working" : "NOT working")<< std::endl;

fftw_plan_with_nthreads(nthreads);
fftwf_plan plan_forward;
fftwf_plan plan_backward;
std::cout << "Creating plans for forward and backward Fast Fourier transform..." << std::endl;
plan_forward=fftwf_plan_dft_r2c_3d(NGRID, NGRID, NGRID, field_to_fourier, Fourierfield, FFTW_ESTIMATE);
plan_backward=fftwf_plan_dft_c2r_3d(NGRID, NGRID, NGRID, Fourierfield, field_to_fourier, FFTW_ESTIMATE);

std::copy(field.begin(), field.end(), field_to_fourier);
std::cout << "Executing the forward Fourier transform..." << std::endl;
fftwf_execute(plan_forward);
/*========================
Applying the filter here
========================*/
std::cout << "Applying the " << filtertype << " filter... " << std::endl;
if(filtertype.compare("Gaussian")==0){
        gaussian_f(NGRID, fsize, Fourierfield);
        }    
else if(filtertype.compare("TopHat")==0){
        top_hat_f(NGRID, fsize, Fourierfield);
        }

std::cout << "Executing the backward Fourier transform..." << std::endl;
fftwf_execute(plan_backward);
fftw_plan_with_nthreads(1);
fftwf_destroy_plan(plan_forward);
fftwf_destroy_plan(plan_backward);
fftw_cleanup_threads();

std::copy(field_to_fourier, field_to_fourier+FFTNORM, field.begin());

fftwf_free(Fourierfield);
fftwf_free(field_to_fourier);

//RESCALE THE FIELDS (in 3D FFT transform, a factor of NGRID^3 is gained upon returning to the real space)
std::for_each(field.begin(), field.end(), [&](float& x){ x/=float(FFTNORM);} );
#endif //endif for smoothing filters...
}
void get_PDF_CDF(float rbin, std::string filtertype, std::vector<float> field,
                std::vector<float>& PDF_x, std::vector<int>& PDF_counts, 
   std::vector<float>& PDF, std::vector<float>& CDF){

std::cout << "There are currently " << nthreads << " threads working in parellel" << std::endl;

/*===========================================================
Here we go to Fourier space for applying smoothing filters
=============================================================*/
#ifdef smoothing_filters

std::vector<fftwf_complex> Fourierfield(pow(NGRID,2)*(NGRID/2 +1));

std::cout << "The FFTW multi-threaded calculations are " << (fftw_init_threads() ? "working" : "NOT working")<< std::endl;

fftw_plan_with_nthreads(nthreads);
fftwf_plan plan_forward;
fftwf_plan plan_backward;

std::cout << "Creating plans for forward and backward Fast Fourier transform..." << std::endl;

plan_forward=fftwf_plan_dft_r2c_3d(NGRID, NGRID, NGRID, field.data(), Fourierfield.data(), FFTW_ESTIMATE);
plan_backward=fftwf_plan_dft_c2r_3d(NGRID, NGRID, NGRID, Fourierfield.data(), field.data(), FFTW_ESTIMATE);

std::cout << "Executing the forward Fourier transform..." << std::endl;
fftw_plan_with_nthreads(1);
fftwf_execute(plan_forward);

/*========================
Applying the filter here
========================*/
std::cout << "Applying the " << filtertype << " filter... " << std::endl;

if(filtertype.compare("Gaussian")==0){
        gaussian_f(NGRID, fsize, Fourierfield);
        }

else if(filtertype.compare("TopHat")==0){
        top_hat_f(NGRID, fsize, Fourierfield);
        }

std::cout << "Executing the backward Fourier transform..." << std::endl;
fftwf_execute(plan_backward);
fftwf_destroy_plan(plan_forward);
fftwf_destroy_plan(plan_backward);
fftw_cleanup_threads();


//RESCALE THE FIELDS (in 3D FFT transform, a factor of NGRID^3 is gained upon returning to the real space)
std::for_each(field.begin(), field.end(), [&](float& x){ x/=float(FFTNORM);} );

#endif //endif for smoothing filters...
}
编辑:

我现在完全确定应用过滤器时会发生错误。注释代码的这些部分可以使代码无限期地运行。目前我不知道是什么导致了这个问题。这些函数在程序顶部声明。现在,我使用的是高斯函数,但同样的问题也出现在top-hat-f上。另外,现在从1个线程执行和删除计划

void top_hat_f(int NGRID, float fsize, fftwf_complex* Fourierfield);
void gaussian_f(int NGRID, float fsize, fftwf_complex* Fourierfield);

请尝试本文中描述的分配器。如果这样做有效,您就知道它是关于内存分配的。注意答案下面的注释,我同意。我认为问题在于FFTW要求复杂数组的最后一个维度(在r2c情况下)的大小为NGRID/2+1,所以它是
ix
aka
I
。至少它是正确过滤所必需的。另一方面,看起来您的
LOC
提供了连续的索引,因此它仍然应该访问分配内存块中的所有值。尝试修复索引并重试。在创建计划时设置不同的第三个参数(盲目尝试了4个选项,因此在其中一个计划的第三个插槽中写入NGRID/2+1,两者都有,或者都没有),在某些迭代过程中总会导致一些问题。问题发生在最近一次(第四次迭代)时,我在两个计划中都保留了所有三个参数“NGRID”。我已经把所有的例程都改成了float类型,但那没有用。我在gaussian_f函数中有一个循环来检查越界访问,但似乎没有发生。如果(LOC(i,j,k)>=NGRID*NGRID*(NGRID/2+1)){std::cout我在没有注释掉“应用过滤器部分”时得到的错误is:当我注释掉“./statistics\u calc.exe”中的#pragma指令***错误时也会发生同样的情况:损坏的大小与上一个大小:0x0000000000839b40***我已经检查了唯一的方法,在这种方法中,连续的前向和后向傅里叶变换产生一个恒等式(在按因数N^3重新缩放后)当我在两个计划中都使用NGRID,NGRID,NGRID时。
#define LOC(ix,iy,iz)  (((iz)*NGRID*NGRID + (iy)*NGRID + (ix))    )
void top_hat_f(int NGRID, float fsize, fftwf_complex* Fourierfield);
void gaussian_f(int NGRID, float fsize, fftwf_complex* Fourierfield);