3

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

由于 SVD 计算依赖于 shape 的输入矩阵(159459,159459),因此这里没有解决我的目标。

我曾尝试使用:

  • 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

4

1 回答 1

3

内存大小很重要,延迟成本接下来会伤害你:

Given mM.shape == [159459, 159459]
givenmM.dtype是默认情况下float(64)
需要有 about:
203.42 [GB]对于 的原始mM[159459, 159459],加上
203.42 [GB]计算的mU[159459, 159459],加上
203.42 [GB]计算的计算的Vh[159459, 159459]
0.0013 [GB]vS[159459]

有史以来最便宜的一步,通过尝试仅线性缩小 2 倍(不超过 4 倍)从float64float32甚至float16不是游戏规则改变者,甚至因numpy效率低下而受到严重惩罚(如果不是内部执行的反向转换高达float64再次 - 我自己的尝试在这方面流血,我在这里分享由此产生的不满,以避免重复我自己的错误,试图首先从最低的挂果开始......)

如果您的分析可能仅适用于 vector vS,则只有标志将通过不返回(因此不为它们保留空间)实例来.svd( ..., compute_uv = False, ... )避免为~ 1/2 [TB]RAM 分配mU腾出空间和Vh

即使是这样的情况也不意味着您的 SLOC 将像报告的0.5 TBRAM 系统一样继续存在。该scipy.linalg.svd()处理将分配内部工作资源,这些资源超出了您的编码范围(当然,除非您自己重构和重新设计scipy.linalg模块,如果不确定,这是公平的考虑非常可能)和配置控制。因此,请注意,即使您测试compute_uv = False-mode 处理,.svd()如果它无法在内部分配不适合当前 RAM 的所需内部使用的数据结构,它仍可能引发错误。

这也意味着即使使用numpy.memmap(),这可能是一个成功的技巧来卸载原始的 RAM 内表示mM(避免第一个需要的一些显着部分203.4 [GB]坐下来并阻止主机 RAM 的使用),但是有使用此技巧必须支付的费用。

我的实验,在较小规模的.memmap-s 上,用于矩阵处理和 ML 优化,产生了1E4 ~ 1E6较慢的处理,因为尽管有智能缓存,但numpy.memmap()-instances 依赖于磁盘 I/O。

最好的结果将来自使用先进的、TB小型的、仅限 SSD 的存储设备,这些设备直接托管在一些快速和低延迟访问总线 M.2 或 PCIx16 上的计算设备上。

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

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

于 2019-07-06T13:08:38.673 回答