Переписать несколько матричных операций, чтобы избежать ошибки памяти? - PullRequest
1 голос
/ 24 февраля 2020

У меня очень большая матрица. buildmatrix - это матрица N на N. Таким образом, sumHamiltonian - это матрица N ^ 2 по N ^ 2. Тогда преобразование (N) представляет собой матрицу N ^ 2 по N (N-1) / 2. (Таким образом, результирующий короткий гамильтониан (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. Есть ли способ переписать это, или еще лучше, все матричные операции, чтобы избежать ошибки памяти?

Ответы [ 2 ]

2 голосов
/ 24 февраля 2020

Одно из предложений - использовать разреженные матрицы. Также, если возможно, сделайте ваш 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 в «разреженную версию».

1 голос
/ 24 февраля 2020

В зависимости от того, сколько у вас избытка памяти, вы можете уменьшить размер ваших матриц, просто используя что-то вроде .astype(np.float32) (например, если текущий dtype равен np.float64).

buildmatrix(N) вызывается дважды в одной строке (то же самое с transform). Если результат детерминированный c (вы просто хотите использовать тот же результат), попробуйте присвоить его переменной, так что его нужно вызывать только один раз.

Эти советы могут немного уменьшить профиль памяти, но может или не может быть достаточно. Я не уверен, что вычисление также может быть упрощено некоторой идентичностью.

...