gpt4 book ai didi

python - 为什么 X.dot(X.T) 在 numpy 中需要这么多内存?

转载 作者:太空狗 更新时间:2023-10-29 23:59:16 24 4
gpt4 key购买 nike

X 是一个 n x p 矩阵,其中 p 远大于 n。假设 n = 1000 和 p = 500000。当我运行时:

X = np.random.randn(1000,500000)
S = X.dot(X.T)

尽管结果大小为 1000 x 1000,但执行此操作最终会占用大量内存。一旦操作完成,内存使用量就会下降。有什么办法解决这个问题吗?

最佳答案

问题不在于 XX.T 是同一内存空间的 View 本身,而是 X.T 是 F 连续的而不是 C 连续的。当然,这必须对于这种情况下的至少一个输入数组必然为真将数组与其转置 View 相乘。

在 numpy < 1.8 中,np.dot 将创建任何 F 排序输入数组的 C 排序副本,而不仅仅是恰好是同一 block View 的那些内存。

例如:

X = np.random.randn(1000,50000)
Y = np.random.randn(50000, 100)

# X and Y are both C-order, no copy
%memit np.dot(X, Y)
# maximum of 1: 485.554688 MB per loop

# make X Fortran order and Y C-order, now the larger array (X) gets
# copied
X = np.asfortranarray(X)
%memit np.dot(X, Y)
# maximum of 1: 867.070312 MB per loop

# make X C-order and Y Fortran order, now the smaller array (Y) gets
# copied
X = np.ascontiguousarray(X)
Y = np.asfortranarray(Y)
%memit np.dot(X, Y)
# maximum of 1: 523.792969 MB per loop

# make both of them F-ordered, both get copied!
X = np.asfortranarray(X)
%memit np.dot(X, Y)
# maximum of 1: 905.093750 MB per loop

如果复制是个问题(例如,当 X 非常大时),您能做些什么?

最好的选择可能是升级到较新版本的 numpy - 正如@perimosocordiae 指出的那样,此性能问题已在 this pull request 中解决.

如果出于某种原因您无法升级 numpy,还有一个技巧可以让您快速执行基于 BLAS 的点积,而无需通过 scipy.linalg 直接调用相关的 BLAS 函数来强制复制。 blas(无耻地从 this answer 偷来的):

from scipy.linalg import blas
X = np.random.randn(1000,50000)

%memit res1 = np.dot(X, X.T)
# maximum of 1: 845.367188 MB per loop

%memit res2 = blas.dgemm(alpha=1., a=X.T, b=X.T, trans_a=True)
# maximum of 1: 471.656250 MB per loop

print np.all(res1 == res2)
# True

关于python - 为什么 X.dot(X.T) 在 numpy 中需要这么多内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21208420/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com