使用 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
,您可以将其存储在内存中(如果需要,对信号进行零填充这样N
是m
的倍数)
对于beta = 0, 1, 2, ... ,m - 1
,请执行以下操作:
将新系列划分为N/m
连续点的m
子区间。
对于每个子区间,将每个第 j 个元素乘以 exp(i*2*pi*j*beta/N)
。这里j
是根据点在整个数据流中相对于第一个的位置来索引的。
对每个子区间的第一个元素求和以产生一个数字,然后对第二个元素求和,依此类推。这可以在从文件中读取点时完成,因此无需在内存中拥有完整的N
点集。
傅立叶变换所得级数,其中包含N/m
个点。
这将为k = ml + beta
和l = 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的主要内容,如果未能解决你的问题,请参考以下文章