我们在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);
}
以&#39; w&#39;开头的变量是模块静态变量,LEN_BUFFER是超大的样本数。 谢谢大家的帮助!!
答案 0 :(得分:0)
这是我的第一个涉及线程的项目,而且我的同事也没有很好的经验,所以我们没有考虑过几个问题。第一个是DETACHABLE和JOINABLE之间的区别:我们的应用程序不必等待线程完成;事实上,这是引导我们进行线程化的问题(主要是等待很长时间才能完成FFT,而这并不是必需的)。我的SW的先前版本是默认的,可加入的,因此分配给该线程的资源从未是免费的。我们没有考虑的第二点是生成线程需要额外的资源。在我的SW的先前版本中,每次必须计算FFT时都生成一个线程;在我们的应用程序中,这大约每10秒或更长时间附加一次,因此显然不重要;而且最快的是FFT开始,用于FFT的数据越少(这是一个很长的故事,但我们可以这样总结);最后,使用互斥和算法的逻辑显然保护了共享资源(同时从线程和主要使用共享资源是不太可能的)。不幸的是,线程生成,经过几个周期使内存饱和(我们不是在PC上工作,而是在一个简单的微处理器上......),这就是分段错误的起源,所以我相信。
我已经用这种方式解决了这个问题:FFT线程是在应用程序启动时生成的,因此它只与主线程一起生成一个线程。在线程内是一个无限循环,周期性地(当前比主循环快4倍)检查指示FFT请求的共享变量:如果为真,则线程在本地读取和复制共享存储器,这些存储器包含FFT输入和其他必要的参数。在处理结束时,输出保存在共享存储器中,另一个标志设置为指示fft可用的主循环。每个共享数据都使用互斥锁访问R / W,包括线程和主数据,并且只有线程使用的数据由互斥锁控制。线程生成为可拆卸而没有任何杀戮或退出,因为线程必须与主要“永远”共存。昨天这个SW运行了几个小时没有问题(我已经手动停止)以及压力条件。