【发布时间】:2023-04-09 04:00:01
【问题描述】:
我正在处理大型矩阵,例如Movielens 20m dataset。我重组了在线文件,使其与页面上提到的尺寸(138000 x 27000)匹配,因为原始文件包含更大的索引(138000 x 131000),但包含很多空列。 只需丢弃那些空列并重新建立索引即可产生所需的维度。
无论如何,将稀疏 csv 文件转换为密集格式的 sn-p 如下所示:
import pandas as pd
from scipy import sparse
# note that the file is not the one described in the link, but the smaller one
X = pd.read_csv("ml-20m-dense.dat", sep=",", header=None)
mat = sparse.coo_matrix((X[2], (X[0], X[1]))).todense()
现在,内存中的估计大小应该接近 138000 * 27000 * 8 / (1024^3) = 27.5 GB。
然而,当我使用 htop 检查进程时,内存消耗仅显示大约 7 GB,尽管保留了大约 32 GB 虚拟内存。
起初我认为这可能是由于 pandas 阅读器或 scipy.sparse 包的一些“效率技巧”,以规避内存消耗。
但即使在我调用我的 PCA 函数之后,它也不会将活动内存消耗增加到应有的量。
请注意,调用 mat.nbytes 会返回估计的确切数量,因此 NumPy 似乎至少知道数据。
(PCA代码供参考:)
from fbpca import pca
result = pca(mat, k=3, raw=False, n_iter=3)
请注意,尽管 fbpca 使用随机算法,并且我只计算前三个分量,code 仍然执行输入矩阵的(单个但完整的)矩阵乘法(更小)随机矩阵。本质上,它仍然必须至少访问输入矩阵中的每个元素一次。
最后一句话也使这与我发现的帖子略有不同,例如this,因为在那篇帖子中,元素从未真正被访问过。
【问题讨论】:
-
7GB + 32GB = 39GB,足以容纳数据。您为什么假设该进程未将数据存储在 32GB 中?
-
它为整个大小保留虚拟内存,但从未真正“直接使用”它。一旦我乘以矩阵,IMO 的活动消耗应该在 27 GB 左右,因为它会访问每个元素。
-
我认为你误解了虚拟内存是什么。
-
您愿意详细说明一下吗?我的意思是,当我乘以矩阵时,它仍应显示为主动消费,对吗?
-
这可能是开始阅读它的好地方:serverfault.com/questions/138427/…。虚拟并不意味着进程未使用的内存,它仅表示分配给当前不在物理内存中的进程的内存。当然要执行必须加载到 ram 然后到 CPU 的矩阵乘法,但是 numpy 一次只乘几个元素。操作系统知道不将整个数组加载到内存中,只加载当前正在操作的部分。