问题的简化版本
我有一个巨大的类似矩阵的数据集,我们现在可以假装它实际上是存储在磁盘上的一个n
逐个n
矩阵作为n^2
IEEE-754 双精度数(请参阅行下方的详细信息,了解这是如何简化的——它可能很重要)。该文件的数量级为千兆字节,但在某个(纯)函数中,我只需要其中n
包含的元素的顺序。确切需要哪些元素是复杂的,而不是像一个简单的切片。
从磁盘读取文件和计算解耦的选项是什么?最重要的是,我想把磁盘上的数据当作内存中的数据来对待(我当然准备向所有参照透明之神发誓,磁盘上的数据不会改变)。我看过mmap和朋友,但一些粗略的测试表明,这些似乎没有足够积极的空闲内存。
如果我需要对内存中保存多少文件进行如此细粒度的控制,我是否必须将我的计算与 IO 结合起来?
更真实的磁盘数据描述
磁盘上的数据实际上并不像描述的那么简单。更接近事实的情况如下:文件以 32 位整数开头n
。然后精确出现以下情况n
:一个 32 位整数m_i
> 0 (1 ≤ i ≤ n),紧随其后的是m_i
IEEE-754 doubles x_(i,1),…,x_(i, m_i)
。(所以,这是一个锯齿状的二维数组)。
在实践中,确定i
和j
需要哪个x_(i, j)
在很大程度上取决于m_i
's. 当处理 mmap 的问题时,读取这么多这些m_i
s 的需要似乎本质上是将整个文件加载到内存中。问题是这一切似乎都停留在那里,我担心我将不得不将我的计算拉入IO
,以便对这个内存的释放进行更细粒度的控制。
此外,“数据结构”实际上由大量这些文件组成,这些文件由它们的文件名参数化。它们加起来大约为 1 GB。
尝试更加挥手,但可能更容易理解问题的版本
假设我在磁盘上有一些由n^2
元素组成的数据。纯 Haskell 函数需要元素的顺序n
,但它们中的哪一个以复杂的方式取决于值。我不想将整个文件加载到内存中,因为它很大。一种解决方案是将我的函数放入IO
monad 并在需要时读出元素,但我称之为“放弃”。mmap让我们将磁盘上的数据视为在内存中,本质上是在操作系统的虚拟内存系统的帮助下进行惰性 IO。这很好,但是由于确定需要哪些数据元素需要访问大量文件,因此 mmap 似乎在内存中保留了太多文件。在实践中,我发现读取我需要的数据来确定我需要的数据实际上需要在使用 mmap 时将整个文件加载到内存中。
我有什么选择?