【问题标题】:Rewrite several matrix operations to avoid memory error?重写几个矩阵运算以避免内存错误?
【发布时间】:2020-06-07 17:16:54
【问题描述】:

我有一个非常大的矩阵。 buildmatrix 是一个 N 乘 N 矩阵。所以 sumHamiltonian 是一个 N^2 × N^2 矩阵。那么 transform(N) 是一个 N^2 乘 N(N-1)/2 矩阵。 (因此得到的 shortHamiltonian(N) 是 N(N-1)/2 乘 N(N-1)/2 矩阵)。矩阵条目也是复数。

如果 N=200,我会收到内存错误。有没有办法改写:

def sumHamiltonian(N):
    return 0.5*(np.kron(buildmatrix(N),np.identity(N))+np.kron(np.identity(N),buildmatrix(N)))

def shortHamiltonian(N):
    return np.matmul(np.transpose(transform(N)),np.matmul(sumHamiltonian(N),transform(N)))

减少内存?

我已经看到了一些减少矩阵乘法内存的方法 (Python/Numpy MemoryError),这很有帮助,但我的内存错误出现在 kronecker 产品上。有没有办法重写这个,或者更好的是,所有的矩阵运算来避免内存错误?

【问题讨论】:

  • 我用一个小的 N 制作数组,并寻找将它们分成块的方法。此外,sum 是 2 个相似的kron 的平均值。由于np.idenity,这些kron 可能是稀疏的。我会寻找特定于这种情况的模式,而不是希望一些通用的“内存保护程序”。 N^4 变大很快,尤其是当你将两个相加时。

标签: python numpy memory out-of-memory


【解决方案1】:

一个建议是使用稀疏矩阵。此外,如果可能,请让您的 buildmatrix 返回一个 dtype 为 np.complex64 而不是 np.complex128 的矩阵。请参见下面的示例:

from scipy import sparse


def buildmatrix(N):
    return (np.random.rand(N, N) + np.random.rand(N, N) * 1j).astype(np.complex64)

N = 100

m = buildmatrix(N)
I = np.identity(N)
sumHamiltonian = 0.5 * (np.kron(m, I) + np.kron(I, m))
print(f'{sumHamiltonian.nbytes * 1e-9} GB')
#1.6 GB

m_s = sparse.csr_matrix(m)
I_s = sparse.identity(N)
sumHamiltonian_s = 0.5 * (sparse.kron(m_s, I_s) + sparse.kron(I_s, m_s))
print(f'{sumHamiltonian_s.data.nbytes * 1e-6} MB')
#31.84 MB

#np.all(sumHamiltonian == sumHamiltonian_s)
#True

同样尝试将您的shortHamiltonian 转换为“稀疏版本”。

【讨论】:

  • 稀疏矩阵改变了我的生活 - 非常感谢您的建议,这正是我所追求的!
  • 很高兴它有帮助!请考虑接受我的回答。
【解决方案2】:

根据您有多少内存过剩,您可以通过使用.astype(np.float32) 之类的东西来减小矩阵的大小(例如,如果当前的dtypenp.float64)。

buildmatrix(N) 在同一行中被调用两次(与transform 相同)。如果结果是确定性的(您只想使用相同的结果),请尝试将其分配给一个变量,以便只需要调用一次。

这些提示可能会稍微减少内存配置文件,但可能不够,也可能不够。我不确定计算是否也可以通过某种身份来简化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    相关资源
    最近更新 更多