使用 Matlab 对大数据 (16gB) 进行 FFT

Posted

技术标签:

【中文标题】使用 Matlab 对大数据 (16gB) 进行 FFT【英文标题】:FFT of large data (16gB) using Matlab 【发布时间】:2014-09-07 00:54:06 【问题描述】:

我正在尝试计算从大小约为 16 GB 的文本文件导入的大量数据的快速傅立叶变换。我试图想办法在matlab中计算它的fft,但是由于我的计算机内存(8gB),它给了我一个内存不足的错误。我尝试使用memmap、textscan,但无法申请获取组合数据的FFT。

谁能指导我如何获得傅立叶变换?我还尝试在远程服务器上使用 C++ 代码获取傅立叶变换(使用定义),但执行需要很长时间。谁能给我一个关于我应该如何处理这些大数据的正确见解?

【问题讨论】:

要么尝试将数据拆分成更小的块,以便您的计算机可以处理它,要么获得更多内存。 @JoachimPileborg 但是将数据分成更小的块会使应用 FFT 变得困难。 FFT 需要访问所有数据 真的很想知道你打算用那个 FFT 做什么? @user3821417:您真的想要拥有数十亿点的 FFT 吗?因为通常在较长的信号上你会计算一个频谱图(它只是在很短的时间间隔内重复计算 FFT) @MSalters 只是作为应用程序示例查看this。应用程序是搜索脉冲星,他们在那篇论文中谈到的数据从 2^29 到 2^33 不等。不了解 OP 的应用,但有时需要对大型数据集进行 FFT。 【参考方案1】:

我也遇到过同样的问题。我最终在一篇论文中找到了解决方案: Extending sizes of effective convolution algorithms。它本质上涉及加载较短的块,乘以相位因子和 FFT,然后加载系列中的下一个块。这给出了完整信号的总 FFT 的采样。然后用不同的相位因子重复该过程多次以填充剩余的点。我将尝试在这里总结(改编自论文中的表二):

    对于长度为 N 的总信号 f(j),确定一个数字 m 或更短的块,每个长度为 N/m,您可以将其存储在内存中(如果需要,对信号进行零填充这样Nm 的倍数)

    对于beta = 0, 1, 2, ... ,m - 1,请执行以下操作:

    将新系列划分为N/m 连续点的m 子区间。

    对于每个子区间,将每个第 j 个元素乘以 exp(i*2*pi*j*beta/N)。这里j是根据点在整个数据流中相对于第一个的位置来索引的。

    对每个子区间的第一个元素求和以产生一个数字,然后对第二个元素求和,依此类推。这可以在从文件中读取点时完成,因此无需在内存中拥有完整的N 点集。

    傅立叶变换所得级数,其中包含N/m 个点。

    这将为k = ml + betal = 0, ..., N/m-1 提供F(k)。将这些值保存到磁盘。

    转至 2,并继续使用 beta 的下一个值。

【讨论】:

【参考方案2】:

使用自己的代码实现 FFT 可能会更好。

FFT 算法有一个“butterfly”运算。因此,您可以将整个步骤分成更小的块。

文件太大,普通电脑无法处理。但 FFT 不需要一次所有数据。它总是可以从 2 点(也许 8 点更好)FFT 开始,您可以通过级联阶段来建立。这意味着您可以一次read only a few points,进行一些计算,然后保存您的数据到磁盘。下次您进行另一次迭代时,您可以从磁盘读取保存的数据。

根据您构建数据结构的方式,您可以将所有数据存储在一个文件中,并使用指针读取/保存它(在 Matlab 中它只是一个数字);或者您可以将每个点存储在一个单独的文件中,生成数十亿个文件并通过文件名区分它们。

这个想法是您可以将计算转储到磁盘,而不是内存。当然它需要这么大的磁盘空间,这是比较可行的。


我可以给你看一段伪代码。根据您的原始数据(即 16GB txt 文件)的数据结构,实现方式会有所不同,但您可以轻松操作,因为您拥有该文件。我将从 2 点 FFT 开始,然后处理 this wikipedia picture 中的 8 点样本。

1.对x 进行2 点FFT,生成y,左起第三列白色圆圈。

read x[0], x[4] from file 'origin'
y[0] = x[0] + x[4]*W(N,0);
y[1] = x[0] - x[4]*W(N,0);
save y[0], y[1] to file 'temp'
remove x[0], x[4], y[0], y[1] from memory
read x[2], x[6] from file 'origin'
y[2] = x[2] + x[6]*W(N,0);
y[3] = x[2] - x[6]*W(N,0);
save y[2], y[3] to file 'temp'
remove x[2], x[6], y[2], y[3] from memory
....

2.对y进行2点FFT,生成z,第5列白色圆圈。

3.对z 进行2 点FFT,生成最终结果X

基本上Cooley–Tukey FFT algorithm的设计目的是让你可以分割数据并逐块计算,因此可以处理大量数据。我知道这不是常规方式,但是如果您可以查看该***页面的中文版,您可能会发现许多图片可以帮助您了解它是如何划分点的。

【讨论】:

谢谢 Yvon,我仍然不清楚如何分离数据、应用 fft、重新组合它们。你能举个例子吗? 我向您展示了第一次迭代,从 x 到 y。您可以类似地执行以下迭代。【参考方案3】:

这取决于您需要的 FFT 分辨率。如果您只需要 1024 个点的 FFT,那么您可以将数据重塑为,或按顺序将其读取为 N x 1024 块。获得这种格式后,您可以将每个 FFT 结果的输出添加到 1024 点复数累加器。

如果您在 FFT 之后需要相同的分辨率,那么您需要更多内存,或者 Matlab 中不包含的特殊 fft 例程(但我不确定在数学上是否可以进行部分 FFT通过缓冲小块以获得全分辨率)。

【讨论】:

谢谢你,你能详细说明一下吗,我不太明白你的意思。我是matlab新手,谢谢

以上是关于使用 Matlab 对大数据 (16gB) 进行 FFT的主要内容,如果未能解决你的问题,请参考以下文章

使用Matlab进行大数据FFT(16gB)

如何在 Matlab 中对大数据进行归一化?

对大文件大小的顺序 i/o 操作进行优化

急!!请教高手:如何用MATLAB程序高效地对大批量的数据进行处理和保存?(回答满意追加5分)

按GB 11643标准对大陆身份证号码分析验证

对大文件排序