将数据写入NumPy memmap仍会加载到RAM内存中

7

我正在通过IPython Notebook测试NumPy的memmap,使用以下代码:

Ymap = np.memmap('Y.dat', dtype='float32', mode='w+', shape=(5e6, 4e4))

正如您所看到的,Ymap 的形状非常大。我正在尝试像填充稀疏矩阵一样填充 Ymap。我没有使用 scipy.sparse 矩阵,因为最终需要将其与另一个密集矩阵进行点积,而这显然不会适合内存。

总之,我正在执行一系列非常长的索引操作:

Ymap = np.memmap('Y.dat', dtype='float32', mode='w+', shape=(5e6, 4e4))
with open("somefile.txt", 'rb') as somefile:
    for i in xrange(5e6):
        # Read a line
        line = somefile.readline()
        # For each token in the line, lookup its j value
        # Assign the value 1.0 to Ymap[i,j]
        for token in line.split():
            j = some_dictionary[token]
            Ymap[i,j] = 1.0

这些操作会快速消耗我的内存。我认为mem-mapping基本上是一种类似于"out-of-core"的numpy.ndarray,但我错了吗?为什么我的内存使用量像疯子一样飙升?


3
如果内存可用,为什么你希望它不使用内存呢?那样会慢上许多个数量级,如果你没有将内存用于其他用途,你就得不到任何成本效益。在极少数情况下,你可能比操作系统更了解内存需求(例如,你有一大块你很久没碰过的东西,但即将连续扫描N次),那么你可能需要手动使用“madvise”/“mprotect”或Win32等价物,但除此之外,你根本不需要担心它。快速使用你的RAM是正确的做法,所以放心使用吧。 - abarnert
1
看一下PyTables,它可能是一个很好的工具。 - M4rtini
我认为PyTables不支持点积,这就是为什么我在研究memmap的原因。 - richizy
PyTables不支持使用快速便捷函数计算巨大矩阵的点积。但是手动实现点积算法应该相当简单直接。 - M4rtini
@richizy:使用非常稀疏的mmap'd数组进行点积运算,可能比使用scipy.sparse.cs{c,r}_matrix慢几个数量级。密集矩阵乘法事先不知道零在哪里,并且将循环遍历所有元素。 - Fred Foo
2个回答

15
一个(非匿名的)mmap是文件和RAM之间的链接,大致上保证了当mmap的RAM已满时,数据将被分页到给定的文件而不是到交换磁盘/文件,并且当你msyncmunmap它时,整个RAM区域会写入文件。操作系统通常遵循慵懒策略以进行磁盘访问(或急切策略以进行RAM访问):只要数据适合内存,它就会一直留在内存中。这意味着具有大mmaps的进程将占用尽可能多的RAM,直到将剩余部分溢出到磁盘为止。
所以你是对的,np.memmap数组是一个离线数组,但它会尽可能多地使用RAM缓存。

1
所以 memmap 基本上是无用的。 - agemO
@agemO,目标不是最小化RAM使用。它可以很好地处理比RAM更大的.npy文件,或者只需要访问其中几个元素而无需从磁盘加载整个文件的大文件。 - user2699
1
目标不是最小化RAM使用。然后我认为:“内存映射文件用于访问磁盘上大文件的小段,而无需将整个文件读入内存。”这真的很误导人。这正是您可以在h5py或某些pandas加载函数中阅读到的句子类型,但在这些情况下,它实际上意味着“让我们逐块读取整个文件!” - agemO

7
根据文档
内存映射文件用于访问磁盘上大文件的小段,而无需将整个文件读入内存。如果访问巨大数组的很少部分,则memmap技巧需要很少的RAM; 如果访问巨大数组的很多部分,则memmap技巧需要很多RAM。在你的特定代码中可能有所帮助的一种解决方法是:在工作流程的逻辑点上定期创建新的mmap对象(并且摆脱旧的对象)。 然后,所需的RAM数量应该大致与这些步骤之间触摸的数组项数成比例。相应地,创建和销毁新的mmap对象需要时间,因此需要权衡考虑。

这是一个有用的解决方案,适用于像我这样内存受限且只需要在从磁盘读取之间进行Order(30ms)延迟的人。 - catubc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接