我正在尝试计算100,000个向量的余弦相似度,并且每个向量都有200,000个维度。
从阅读其他问题我知道memmap,PyTables和h5py是处理这类数据的最佳选择,我目前正在使用两个memmaps;一个用于读取向量,另一个用于存储余弦相似性矩阵。
这是我的代码:
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]
和wmat[:,i/j]
,存储在内存中??
如果没有,我做错了什么,我该如何解决?
感谢您的任何建议!
编辑:我刚刚意识到htop报告的系统内存占用总量为12G,所以它似乎正在工作......那里的任何人都可以启发我吗? RES现在是111G ......EDIT2:memmap是从1D数组创建的,该数组由很多很多长小数组成,非常接近0,形状符合所需的尺寸。然后,memmap看起来像这样。
memmap([[ 9.83721223e-03, 4.42584107e-02, 9.85033578e-03, ...,
-2.30691545e-07, -1.65070799e-07, 5.99395837e-08],
[ 2.96711345e-04, -3.84307391e-04, 4.92968462e-07, ...,
-3.41317722e-08, 1.27959347e-09, 4.46846438e-08],
[ 1.64766260e-03, -1.47337747e-05, 7.43660202e-07, ...,
7.50395136e-08, -2.51943163e-09, 1.25393555e-07],
...,
[ -1.88709000e-04, -4.29454722e-06, 2.39720287e-08, ...,
-1.53058717e-08, 4.48678211e-03, 2.48127260e-07],
[ -3.34207882e-04, -4.60275148e-05, 3.36992876e-07, ...,
-2.30274532e-07, 2.51437794e-09, 1.25837564e-01],
[ 9.24923862e-04, -1.59552854e-03, 2.68354822e-07, ...,
-1.08862665e-05, 1.71283316e-07, 5.66851420e-01]])
答案 0 :(得分:8)
就内存使用而言,目前您正在做的事情没有什么特别的错误。 Memmap数组在OS级别处理 - 要写入的数据通常保存在临时缓冲区中,并且只在OS认为必要时才提交到磁盘。在刷新写缓冲区之前,您的操作系统绝不允许您耗尽物理内存。
我建议不要在每次迭代时调用flush
,因为这会让你的操作系统决定何时写入磁盘以达到最大效率。目前你只是一次编写单独的浮动值。
就IO和CPU效率而言,一次单行操作几乎肯定不是最理想的。对于大的,连续的数据块,读取和写入通常更快,如果使用向量化可以一次处理多行,则计算速度可能会快得多。一般的经验法则是处理数组中适合内存的大块(包括计算过程中创建的任何中间数组)。
Here's an example显示通过在适当大小的块中处理它们可以加快memmapped阵列上的操作速度。
另一个可以产生巨大差异的是输入和输出数组的内存布局。默认情况下,np.memmap
为您提供C连续(行主要)数组。因此,按列访问wmat
将非常低效,因为您正在寻址磁盘上的非相邻位置。如果wmat
在磁盘上是F-contiguous(column-major),或者你是按行访问它,那么你会好得多。
同样的一般建议适用于使用HDF5而不是memmaps,但请记住,使用HDF5时,您必须自己处理所有内存管理。
答案 1 :(得分:7)
内存映射正如名称所示:将(虚拟)磁盘扇区映射到内存页面。内存由操作系统按需管理。如果有足够的内存,系统会将部分文件保留在内存中,可能会填满整个内存,如果没有足够的内存,系统可能会丢弃从文件读取的页面,或者可能将它们交换到交换空间。通常,您可以依赖操作系统尽可能高效。