【发布时间】:2017-10-26 22:51:58
【问题描述】:
我们在 i.MX53(基于 Linux 的 SO)上有一个 C 软件,它必须计算 FFT;为此,我们采用了 FFTW 库。出于性能原因,我们决定使用单独的线程将 FFT 从主应用程序中分离出来。整个应用程序似乎可以正常工作,但一段时间后,我们在 fftwf_execute 的对应关系中出现了分段错误。我确信这一点,因为没有这个单一的指令,我们就没有分段错误。我们进行了几次尝试,但问题仍然存在。这里是线程函数的一部分:
void* vGestDiag_ThreadFFT( void* unused )
{
Int32U idx = 0, idxI = 0, idxJ = 0, idxZ = 0, idxK = 0;
Flo32 lfBufferAccm_chn01[LEN_BUFFER_SAMPLES];
Flo32 lfBufferAccm_chn02[LEN_BUFFER_SAMPLES];
Flo64 dblBufferFFT[LEN_BUFFER_SAMPLES];
Int32U ulCntUtilSample = 0;
float *in;
fftwf_complex *out;
fftwf_plan plan;
/* other variables.... */
/* Init */
memset(lfBufferAccm_chn01, 0x00, LEN_BUFFER_SAMPLES*sizeof(Flo32));
memset(lfBufferAccm_chn02, 0x00, LEN_BUFFER_SAMPLES*sizeof(Flo32));
memset(dblBufferFFT, 0x00, LEN_BUFFER_SAMPLES*sizeof(Flo64));
/* other local memsets .... */
/* Inputs */
pthread_mutex_lock(&lockIN);
ulCntUtilSample = wulCntUtilSample;
/* other inputs.... */
for (idxJ = 0; idxJ < ulCntUtilSample; idxJ++)
{
boBuffCirc_ReadBuffer(&wulBufferAcc01, &ulTmpValue);
lfBufferAccm_chn01[idxJ] = (Flo32)((((Flo32)ulTmpValue - ACC_Q)/ACC_M) * ACC_U) * wlfSensAcc;
boBuffCirc_ReadBuffer(&wulBufferAcc02, &ulTmpValue);
lfBufferAccm_chn02[idxJ] = (Flo32)((((Flo32)ulTmpValue - ACC_Q)/ACC_M) * ACC_U) * wlfSensAcc;
}
pthread_mutex_unlock(&lockIN);
/* --------- Plan FFT ------------------------- */
in = (float*) fftwf_malloc(sizeof(float) * ulCntUtilSample);
out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * ulCntUtilSample);
fftwf_plan_with_nthreads(1);
plan = fftwf_plan_dft_r2c_1d(ulCntUtilSample, in, out, FFTW_ESTIMATE);
for (idxI = 0; idxI <= 1; idxI++)
{
switch(idxI)
{
case 0:
memcpy(in, lfBufferAccm_chn01, ulCntUtilSample*sizeof(float));
break;
case 1:
memcpy(in, lfBufferAccm_chn02, ulCntUtilSample*sizeof(float));
break;
default:
break;
}
/* --------- FFT ------------------------- */
/* EXEC */
fftwf_execute(plan);
/* Complex -> Real */
for (idxZ = 0; idxZ < ulCntUtilSample; idxZ++)
{
dblBufferFFT[idxZ] = cabs(out[idxZ]);
}
/* --------- End FFT ------------------------- */
/* Post-Processing FFT */
/* post-processing and outputs in module static variables, within mutex */
}
/* DEL plan */
fftwf_destroy_plan(plan);
fftwf_free(in);
fftwf_free(out);
/* exit */
pthread_exit(NULL);
}
以“w”开头的变量是模块静态变量,LEN_BUFFER 相对于样本数量而言过大。 谢谢大家帮忙!!
【问题讨论】:
-
在您发布的代码中看不到任何内存问题。很难推测。
wulCntUtilSample中的值是否始终存在?是否有另一个线程负责重置该值?它永远为零吗?确保您的同步是正确的。在您致电fftwf_execute之前,我会打印出您的缓冲区大小。也许有一些先决条件。如果您正在使用优化进行编译,关闭它们以查看它是否重现可能会很有用。如果您可以获得核心转储,调试器可能会很有用。根本原因可能完全在其他地方。 -
你为什么使用
fftwf_plan_with_nthreads(1)?您是否在代码的其他地方调用了fftw_init_threads/fftw_cleanup_threads?您还分配了比输出所需更多的内存。填充dblBufferFFT时,您正在循环未设置的内存。看起来你犯了错误,生成并提供一个最小的例子是值得的。 -
亲爱的@mfisherkdx,感谢您的回答。很难举个例子,我们在虚拟机上使用“特殊”环境编译,然后上传到目标;通常我们在目标终端上使用 printf 进行调试...
wulCntUtilSample是一个共享目标,所以其他线程(主要线程)设置了这个变量,但我已经将它包含在一个互斥锁中。此外,仅当变量大于 0 时才启动此线程。尊重优化,我没有使用任何特别的东西:CFLAGS=-g -c -Wall -DLINUX -
亲爱的@gavin-portwood,感谢您的回答。
fftw_init_threads在应用程序的初始化中使用(仅一次),而我没有使用fftw_cleanup_threads。 Respectfftwf_plan_with_nthreads(1)设置为 1 以备将来使用,实际上我对使用 FFTW 特定线程没有真正的兴趣(我们正在单核处理器上开发),但我们有兴趣将耗时的 FFT 例程与主程序分开.尊重内存,你是对的,为了避免共享内存和复合操作的问题,我使用了很多线程本地内存,但是初始化了。