【发布时间】:2011-01-25 01:52:29
【问题描述】:
我希望有人可以在下面查看我的代码并提供提示如何加快 tic 和 toc 之间的部分。下面的函数尝试比 Matlab 的内置函数更快地执行 IFFT,因为 (1) 几乎所有 fft 系数箱都为零(即10 到 1000 箱中的10M 到 300M 箱是非零),以及(2)仅保留中间三分之一的 IFFT 结果(前三分之一和最后三分之一被丢弃——因此无需首先计算它们)。
输入变量为:
fftcoef = complex fft-coef 1D array (10 to 1000 pts long)
bins = index of fft coefficients corresponding to fftcoef (10 to 1000 pts long)
DATAn = # of pts in data before zero padding and fft (in range of 10M to 260M)
FFTn = DATAn + # of pts used to zero pad before taking fft (in range of 16M to 268M) (e.g. FFTn = 2^nextpow2(DATAn))
目前,此代码比 Matlab 的 ifft 函数方法长几个数量级,后者计算整个频谱然后丢弃 2/3 的它。例如,如果 fftcoef 和 bin 的输入数据是 9x1 数组(即每个边带只有 9 复 fft 系数;考虑两个边带时 18 pts),以及 DATAn=32781534、FFTn=33554432(即 @987654334 @),则 ifft 方法占用 1.6 秒,而下面的循环占用 700 秒。
我避免使用矩阵来向量化 nn 循环,因为有时 fftcoef 和 bin 的数组大小可能高达 1000 pts 长,而 260Mx1K 矩阵对于内存来说太大了,除非它可以以某种方式分手。
非常感谢任何建议!提前致谢。
function fn_fft_v1p0(fftcoef, bins, DATAn, FFTn)
fftcoef = [fftcoef; (conj(flipud(fftcoef)))]; % fft coefficients
bins = [bins; (FFTn - flipud(bins) +2)]; % corresponding fft indices for fftcoef array
ttrend = zeros( (round(2*DATAn/3) - round(DATAn/3) + 1), 1); % preallocate
start = round(DATAn/3)-1;
tic;
for nn = start+1 : round(2*DATAn/3) % loop over desired time indices
% sum over all fft indices having non-zero coefficients
arg = 2*pi*(bins-1)*(nn-1)/FFTn;
ttrend(nn-start) = sum( fftcoef.*( cos(arg) + 1j*sin(arg));
end
toc;
end
【问题讨论】:
-
请参阅fftw.org/pruned.html 了解潜在节省的分析。这可能不值得。
-
您正在查看
length(bins)*(2*DATAn/3)操作,如果2*length(bins)/3 > lg(DAtan)则优于DATAn*lg(DATAn)的 FFT 方法(因为 FFTW 处理非 2 的变换大小,我忽略了零填充)。对于 10 个 bin 和 2^25 个输出点的情况,即“20/3 > 25”,这是提高 3 倍的潜在因素。一旦达到 75 个 FFT 系数,您就失去了优势。你必须用 C 语言编写算法并维护它。 -
感谢 mtrw,我几天前查看了上面的链接。它最初给了我希望,因为它说:“正因为如此,我不建议考虑修剪 1d FFT,除非你想要 1% 或更少的输出(和/或如果你的 1% 或更少的输入是非零的) 。”就我而言,我的输入(IDFT 的系数)中只有不到 0.00001% 是非零的。我认为这应该是提高速度的主要原因,而不是您上面提到的 3 改进因素。