我想在大数组M[159459,159459]上执行SVD。

由于SVD计算取决于形状为(159459,159459)的输入矩阵,因此该here不能满足我的目标。

我尝试使用:


scipy.linalg.svd
scipy.linalg.svd(check_finite=False)
将驱动程序更改为lapack_driver='gesvd
numpy.linalg.svd


但是,我总是收到MemoryError。最后,我想计算完整的SVD,因为我想执行Procrustes分析,即如果M是我现在拥有的矩阵,则需要M = USV'

import numpy as np
from scipy import linalg

#M = np.load("M.npy")
M = np.random.rand(159459,159459)
U, s, Vh = linalg.svd(M, check_finite=False, lapack_driver='gesvd)


一切都失败了。

我的系统详细信息:


  $ cat /proc/meminfo
  MemTotal: 527842404 kB
  MemFree: 523406068 kB
  MemAvailable: 521659112 kB

最佳答案

内存大小很重要,延迟成本会伤害您下一个:

在给定mM.shape == [159459, 159459]的情况下,给定的mM.dtype默认为float(64),将需要具有以下内容:203.42 [GB]表示mM[159459, 159459]的原始名称,加上203.42 [GB]表示计算出的mU[159459, 159459],再加上为计算出的203.42 [GB] Vh[159459, 159459]为计算出的0.0013 [GB]

尝试从vS[159459]float64或什至float32的仅线性缩小比例为2(且不超过4)的系数,这是有史以来最便宜的步骤,它不会改变游戏规则,甚至会受到效率低下(如果未在内部进行高达float16的反向转换-我自己的尝试就此止步不前,以至于我在这里遇到了不满意之处,以避免在尝试从最低限度的挂起开始重复自己的错误水果第一...)

如果您的分析仅适用于向量numpy,则仅float64标志将通过不返回(因此不为其保留空间)实例来避免为大约vS RAM分配留出空间。和.svd( ..., compute_uv = False, ... )

即使是这样的情况,也并不意味着您的SLOC会像报告的~ 1/2 [TB] RAM系统那样存活。 mU处理将分配内部工作资源,这些资源不在您的编码范围内(请确保,除非您自行重构和重新设计Vh模块,如果不确定,可以认为这很可能)和配置控制。因此,请注意,即使在测试0.5 TB处理模式时,如果scipy.linalg.svd()无法在内部分配不适合当前RAM的所需内部使用的数据结构,它仍可能会引发错误。

这也意味着即使使用scipy.linalg,这也可能是卸载原始compute_uv = False的RAM中表示的成功诀窍(避免了第一个所需.svd()的显着部分搁置并阻止使用主机RAM),但使用此技巧需要支付一些费用。

我的实验在较小的numpy.memmap() -s规模下,用于矩阵处理和ML优化时,产生的mM速度较慢,因为尽管进行了智能缓存,但203.4 [GB]实例仍依赖于磁盘I / O。

最好的结果将来自使用先进的.memmap大小,仅SSD的存储设备,该设备直接托管在某些快速且低延迟的访问总线M.2或PCIx16上的计算设备上。

最后的经验,可能还不想在这里听到:

使用更大的基于主机的RAM(这意味着使用多TB计算设备)是更安全的方法。如果降低的性能和其他费用在您的项目预算之内,则测试上述建议的步骤将有所帮助。如果没有,请在您的母校或项目最近的研究中心使用HPC中心,在该中心通常使用这种多TB计算设备。

10-06 06:12