磁盘中巨大的矩阵状结构的小子集透明

gsp*_*spr 5 haskell on-disk

问题的简化版本

我有一个巨大的矩阵状的数据集,我们现在可以假装实际上是一个n-by- n矩阵存储在磁盘上的n^2IEEE-754双精度(详情请参阅该线之下如何,这是一个简化-它可能是重要的).该文件大约为千兆字节,但在某个(纯)函数中,我只需要n包含在其中的元素的顺序.究竟需要哪些元素是复杂的,而不是简单的切片.

从磁盘和计算中读取文件的解耦有哪些选择?最重要的是,我想把磁盘上的数据看作是在内存中(我当然准备向所有参考透明度的神发誓,磁盘上的数据不会改变).我看过mmap和朋友,但是一些粗略的测试显示这些似乎没有足够的自由记忆.

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


对磁盘数据的更诚实的描述

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

在实践中,确定i和j针对x_(i, j)需要高度依赖于m_i的.当用mmap解决问题时,需要读取这么多m_is似乎基本上将整个文件加载到内存中.问题是这一切似乎都停留在那里,我担心我必须将我的计算拉进去,IO以便对释放这个内存进行更细粒度的控制.

而且,"数据结构"实际上由大量按文件名参数化的文件组成.总之它们总量约一千兆字节.


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

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

我有什么选择?

scl*_*clv 1

我建议你编写一个完全在 IO 中的接口,其中你有一个抽象类型,其中包含 aHandle和有关数据整体结构的信息(也许是所有 s,m_i如果你可以容纳它们),并且这是补充IO通过在句柄中查找来读出数据的精确位的操作。

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

假设您不担心在背后“交换”文件,您可以获得一个可以纯粹推理的接口,而它实际上在IO必要时对您所需的内存进行显式控制。