5

问题的简化版本

我有一个巨大的类似矩阵的数据集,我们现在可以假装它实际上是存储在磁盘上的一个n逐个n矩阵作为n^2IEEE-754 双精度数(请参阅行下方的详细信息,了解这是如何简化的——它可能很重要)。该文件的数量级为千兆字节,但在某个(纯)函数中,我只需要其中n包含的元素的顺序。确切需要哪些元素是复杂的,而不是像一个简单的切片。

从磁盘读取文件和计算解耦的选项是什么?最重要的是,我想把磁盘上的数据当作内存中的数据来对待(我当然准备向所有参照透明之神发誓,磁盘上的数据不会改变)。我看过mmap朋友,但一些粗略的测试表明,这些似乎没有足够积极的空闲内存。

如果我需要对内存中保存多少文件进行如此细粒度的控制,我是否必须将我的计算与 IO 结合起来?


更真实的磁盘数据描述

磁盘上的数据实际上并不像描述的那么简单。更接近事实的情况如下:文件以 32 位整数开头n。然后精确出现以下情况n:一个 32 位整数m_i> 0 (1 ≤ i ≤ n),紧随其后的是m_iIEEE-754 doubles x_(i,1),…,x_(i, m_i)。(所以,这是一个锯齿状的二维数组)。

在实践中,确定ij需要哪个x_(i, j)在很大程度上取决于m_i's. 当处理 mmap 的问题时,读取这么多这些m_is 的需要似乎本质上是将整个文件加载到内存中。问题是这一切似乎都停留在那里,我担心我将不得不将我的计算拉入IO,以便对这个内存的释放进行更细粒度的控制。

此外,“数据结构”实际上由大量这些文件组成,这些文件由它们的文件名参数化。它们加起来大约为 1 GB。


尝试更加挥手,但可能更容易理解问题的版本

假设我在磁盘上有一些由n^2元素组成的数据。纯 Haskell 函数需要元素的顺序n,但它们中的哪一个以复杂的方式取决于值。我不想将整个文件加载到内存中,因为它很大。一种解决方案是将我的函数放入IOmonad 并在需要时读出元素,但我称之为“放弃”。mmap让我们将磁盘上的数据视为在内存中,本质上是在操作系统的虚拟内存系统的帮助下进行惰性 IO。这很好,但是由于确定需要哪些数据元素需要访问大量文件,因此 mmap 似乎在内存中保留了太多文件。在实践中,我发现读取我需要的数据来确定我需要的数据实际上需要在使用 mmap 时将整个文件加载到内存中。

我有什么选择?

4

1 回答 1

1

我建议您编写一个完全在 IO 中的接口,其中您有一个抽象类型,其中包含 aHandle和有关数据整体结构的信息(m_i如果可以适合它们,可能是所有 s),这由IO通过在句柄中查找来读取数据的精确位的操作。

然后我会简单地将这个接口包装在一堆unsafePerformIO调用中!从某种意义上说,这实际上是mmap在幕后所做的。您只是以更明确的管理方式这样做。

假设您无论如何都不担心“交换”背后的文件,您可以获得一个您可以完全推理的接口,而它实际上IO在必要时可以显式控制您需要的内存。

于 2015-02-21T06:56:36.047 回答