如何有效地读写太大而无法放入内存的文件?

2024-09-30 02:22:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图计算100000个向量的余弦相似性,每个向量都有200000个维度。在

通过阅读其他问题,我知道memmap、PyTables和h5py是我处理此类数据的最佳选择,我目前正在处理两个memmap;一个用于读取向量,另一个用于存储余弦相似性矩阵。在

这是我的代码:

import numpy as np
import scipy.spatial.distance as dist

xdim = 200000
ydim = 100000

wmat = np.memmap('inputfile', dtype = 'd', mode = 'r', shape = (xdim,ydim))
dmat = np.memmap('outputfile', dtype = 'd', mode = 'readwrite', shape = (ydim,ydim))

for i in np.arange(ydim)):
    for j in np.arange(i+1,ydim):
        dmat[i,j] = dist.cosine(wmat[:,i],wmat[:,j])
        dmat.flush()

目前,htop报告说,我正在使用224G的VIRT内存和91.2G的RES内存,这两个内存正在稳步攀升。在我看来,在整个过程结束时,整个输出矩阵都将存储在内存中,这是我试图避免的。在

问题: 这是memmaps的正确用法吗?我是否以内存高效的方式写入输出文件(我的意思是只有输入和输出文件的必要部分,即dmat[i,j]和{}存储在内存中)?在

如果没有,我做错了什么,我该怎么解决?在

谢谢你的建议!在

编辑:我刚刚意识到htop报告的系统内存总使用量为12G,所以它似乎在工作。。。有谁能启发我?RES现在是111克。。。在

编辑2:memmap是从一个1D数组中创建的,这个数组由许多非常接近0的长小数组成,这些小数被塑造成所需的维度。memmap看起来像这样。在

^{pr2}$

Tags: 内存importmodedistasnp矩阵相似性
2条回答

在内存使用方面,你现在所做的没有什么特别的错误。Memmapped数组是在操作系统级别处理的,要写入的数据通常保存在临时缓冲区中,只有在操作系统认为有必要时才提交到磁盘。在刷新写缓冲区之前,您的操作系统不应该允许您耗尽物理内存。在

我建议不要在每次迭代时调用flush,因为这样做会使操作系统无法决定何时写入磁盘,从而最大限度地提高效率。现在你一次只写单个的浮点值。在


就IO和CPU效率而言,一次在一条线路上操作几乎肯定是次优的。对于大的、连续的数据块,读和写通常更快,同样,如果可以使用向量化同时处理许多行,则计算可能会快得多。一般的经验法则是在内存中处理尽可能大的数组块(包括在计算过程中创建的任何中间数组)。在

Here's an example显示通过在适当大小的块中处理memmapped数组,可以在多大程度上加快操作速度。在

另一个可以产生巨大差异的是输入和输出数组的内存布局。默认情况下,np.memmap提供一个C-连续(row major)数组。因此,按列访问wmat将非常低效,因为您正在处理磁盘上不相邻的位置。如果wmat在磁盘上是F-连续的(列major),或者是按行访问它,情况会好得多。在

同样的一般建议适用于使用HDF5而不是memmaps,不过请记住,使用HDF5,您必须自己处理所有的内存管理。在

内存映射正是顾名思义:将(虚拟)磁盘扇区映射到内存页。内存由操作系统按需管理。如果有足够的内存,系统会将部分文件保存在内存中,可能会填满整个内存;如果内存不足,系统可能会丢弃从文件中读取的页面或将它们交换到交换空间中。正常情况下,你可以信赖的操作系统是尽可能高效的。在

相关问题 更多 >

    热门问题