我想对一个内核长度为16000的长度为4000 * 270的信号进行线性卷积。该信号不是固定的,而内核是固定的。为了我的目的,需要多次重复此操作,因此我想尽快提高速度。我可以用R或C来实现这种卷积。
起初,我尝试在R中进行卷积,但是速度不能满足我的需要。我尝试通过迭代来完成,但是速度太慢。我也尝试过使用FFT进行此操作,但是由于信号和内核都很长,因此FFT并没有提高很多速度。
然后,我决定在C中进行迭代卷积。但是C似乎无法处理如此大量的计算,并且经常报告错误。即使工作正常,它仍然非常缓慢。我也尝试在C中进行fft卷积,但是程序始终关闭。
我从我的一个朋友那里找到了这段代码,不确定原始来源。如果有版权问题,我将其删除。这是我在C中执行fft所使用的C代码,但程序无法处理长度为2097152的长向量(最小幂2大于或等于信号向量长度) )。
#define q 3 /* for 2^3 points */
#define N 2097152 /* N-point FFT, iFFT */
typedef float real;
typedef struct{real Re; real Im;} complex;
#ifndef PI
# define PI 3.14159265358979323846264338327950288
#endif
void fft( complex *v, int n, complex *tmp )
{
if(n>1) { /* otherwise, do nothing and return */
int k,m;
complex z, w, *vo, *ve;
ve = tmp;
vo = tmp+n/2;
for(k=0; k<n/2; k++) {
ve[k] = v[2*k];
vo[k] = v[2*k+1];
}
fft( ve, n/2, v ); /* FFT on even-indexed elements of v[] */
fft( vo, n/2, v ); /* FFT on odd-indexed elements of v[] */
for(m=0; m<n/2; m++) {
w.Re = cos(2*PI*m/(double)n);
w.Im = -sin(2*PI*m/(double)n);
z.Re = w.Re*vo[m].Re - w.Im*vo[m].Im; /* Re(w*vo[m]) */
z.Im = w.Re*vo[m].Im + w.Im*vo[m].Re; /* Im(w*vo[m]) */
v[ m ].Re = ve[m].Re + z.Re;
v[ m ].Im = ve[m].Im + z.Im;
v[m+n/2].Re = ve[m].Re - z.Re;
v[m+n/2].Im = ve[m].Im - z.Im;
}
}
return;
}
void ifft( complex *v, int n, complex *tmp )
{
if(n>1) { /* otherwise, do nothing and return */
int k,m;
complex z, w, *vo, *ve;
ve = tmp;
vo = tmp+n/2;
for(k=0; k<n/2; k++) {
ve[k] = v[2*k];
vo[k] = v[2*k+1];
}
ifft( ve, n/2, v ); /* FFT on even-indexed elements of v[] */
ifft( vo, n/2, v ); /* FFT on odd-indexed elements of v[] */
for(m=0; m<n/2; m++) {
w.Re = cos(2*PI*m/(double)n);
w.Im = sin(2*PI*m/(double)n);
z.Re = w.Re*vo[m].Re - w.Im*vo[m].Im; /* Re(w*vo[m]) */
z.Im = w.Re*vo[m].Im + w.Im*vo[m].Re; /* Im(w*vo[m]) */
v[ m ].Re = ve[m].Re + z.Re;
v[ m ].Im = ve[m].Im + z.Im;
v[m+n/2].Re = ve[m].Re - z.Re;
v[m+n/2].Im = ve[m].Im - z.Im;
}
}
return;
}
我发现此页面谈论长信号卷积https://ccrma.stanford.edu/~jos/sasp/Convolving_Long_Signals.html 但是我不确定如何在其中使用这个想法。任何想法都会受到感激,我准备提供有关我的问题的更多信息。
答案 0 :(得分:0)
根据您引用的CCRMA论文,最常见的高效长FIR滤波器方法是使用FFT / IFFT重叠相加(或重叠保存)快速卷积。只需将数据切成更适合FFT库和处理器数据高速缓存大小的较短块,至少填充滤波器内核长度,FFT滤波器零填充,然后在每次IFFT之后依次叠加-添加余数/尾数。
巨大的长FFT很可能会破坏处理器的缓存,这很可能在任何算法O(NlogN)加速中都占主导地位。