Python 中的 SVD 内存错误

SVD MemoryError in Python

我想对大数组执行 SVD M[159459,159459]

由于 SVD 计算取决于形状为 (159459,159459) 的输入矩阵,因此 here 无法实现我的目标。

我试过使用:

但是,我总是遇到 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]

有史以来最便宜的步骤,通过尝试将 linear-only 缩小 2 倍(且不超过 4),从 float64float32 甚至 float16不是游戏规则的改变者,甚至因 numpy 效率低下而受到严重惩罚(如果没有在内部执行 back-conversions 再次达到 float64 - 我自己的尝试在这方面如此流血,我分享了结果在这里不满意,以免重复我自己的错误,试图从最低的挂果开始......)

如果您的分析可能仅适用于向量 vS,只有 .svd( ..., compute_uv = False, ... ) 标志将避免生成 space 大约~ 1/2 [TB] RAM-allocations 通过不返回(因此不为他们保留 space )实例 mUVh.

即使是这种情况也不意味着您的 SLOC 会像报告中那样存活下来 0.5 TB RAM-system。 scipy.linalg.svd() 处理将分配内部工作资源,这超出了您的编码范围(当然,除非您 re-factor 和 re-design 您自己的 scipy.linalg 模块,这是公平地考虑非常可能,如果不确定)和配置控制。因此,请注意,即使您测试 compute_uv = False 处理模式,.svd() 仍可能会抛出错误,如果它无法在内部分配 required internally used data-structures,则不会适合当前内存。

这也意味着即使使用numpy.memmap(),这可能是一个成功的技巧off-load in-RAM表示原始mM(避免第一个需要的某些显着部分 203.4 [GB] 坐下并阻止主机 RAM 的使用) ,但使用此技巧需要付出一定的代价。

我的实验,在 .memmap-s 的较小尺度上,用于矩阵处理和 ML-optimisations, 产量大约 1E4 ~ 1E6 处理速度较慢 因为尽管有智能缓存,numpy.memmap()-实例依赖于 disk-I/O.

最好的结果将来自于使用先进的、TB 大小、SSD-only-storage 设备,在一些快速和 low-latency access-bus M 上托管在计算设备上。 2 或 PCIx16。

最后一段经验,大家可能还不想听:

使用更大的 host-based RAM,这意味着使用 multi-TB 计算设备,是更安全的方法。如果降低的性能和额外费用在您项目的预算范围内,则测试上述建议的步骤将有所帮助。如果没有,请前往您的母校或您项目最近的研究中心使用 HPC 中心,这些 multi-TB 计算设备正在共同使用。