Joj*_*ing 19 python memory-management numpy
我试图计算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()
Run Code Online (Sandbox Code Playgroud)
目前,htop报告说我正在使用224G的VIRT内存,而91.2G的RES内存正在稳步攀升.在我看来,在整个过程结束时,整个输出矩阵将存储在内存中,这是我试图避免的.
问:这是memmaps的正确用法,我在记忆有效的方式写入到输出文件(我的意思是,只有输入和输出文件的必要部分,即dmat[i,j]和wmat[:,i/j],存储在内存中)?
如果没有,我做错了什么,我该如何解决这个问题呢?
感谢您的任何建议!
编辑:我刚刚意识到htop报告的总体系统内存使用量为12G,所以它似乎正在起作用......那里有谁可以开导我?RES现在是111G ......
编辑2:memmap是从一维数组创建的,该数组由很多很长的小数组成,非常接近于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]])
Run Code Online (Sandbox Code Playgroud)
就内存使用而言,目前您正在做的事情没有什么特别的错误.Memmap数组在OS级别处理 - 要写入的数据通常保存在临时缓冲区中,并且只在OS认为必要时才提交到磁盘.在刷新写缓冲区之前,您的操作系统绝不允许您耗尽物理内存.
我建议不要flush在每次迭代时调用,因为这会让你的操作系统决定何时写入磁盘以最大限度地提高效率.目前,您只是一次编写单个浮点值.
就IO和CPU效率而言,一次在单行上运行几乎肯定不是最理想的.对于大的,连续的数据块,读取和写入通常更快,如果使用向量化可以一次处理多行,则计算速度可能会快得多.一般的经验法则是处理数组中适合内存的大块(包括计算过程中创建的任何中间数组).
这是一个示例,显示了通过在适当大小的块中处理它们可以加快memmapped阵列上的操作速度.
另一个可以产生巨大差异的是输入和输出数组的内存布局.默认情况下,np.memmap为您提供C-contiguous(行主要)数组.wmat因此,按列访问将非常低效,因为您正在寻址磁盘上的非相邻位置.如果wmat在磁盘上是F-contiguous(列主要),或者如果你是按行访问它,那么你会好得多.
相同的一般建议适用于使用HDF5而不是memmaps,但请记住,使用HDF5时,您必须自己处理所有内存管理.
内存映射正如名称所示:将(虚拟)磁盘扇区映射到内存页面.内存由操作系统按需管理.如果有足够的内存,系统会将部分文件保留在内存中,可能会填满整个内存,如果没有足够的内存,系统可能会丢弃从文件中读取的页面,或者可能将它们交换到交换空间.通常,您可以依赖OS尽可能高效.
| 归档时间: |
|
| 查看次数: |
1672 次 |
| 最近记录: |