Python/Numpy MemoryError

В принципе, я получаю ошибку памяти в python при попытке выполнить алгебраическую операцию на матрице numpy. Переменная u, представляет собой большую матрицу двойного (в неудачном случае ее матрица размером 288x288x156 удваивается. Я получаю эту ошибку только в этом огромном случае, но я могу сделать это на других больших матрицах, просто не эта большая). Вот ошибка Python:

 Traceback (most recent call last):

 File "S:\3D_Simulation_Data\Patient SPM Segmentation\20 pc
t perim erosion flattop\SwSim.py", line 121, in __init__
   self.mainSimLoop()

 File "S:\3D_Simulation_Data\Patient SPM Segmentation\20 pc
t perim erosion flattop\SwSim.py", line 309, in mainSimLoop
   u = solver.solve_cg(u,b,tensors,param,fdHold,resid) # Solve the left hand si
de of the equation Au=b with conjugate gradient method to approximate u

 File "S:\3D_Simulation_Data\Patient SPM Segmentation\20 pc
t perim erosion flattop\conjugate_getb.py", line 47, in solv
e_cg

u = u + alpha*p

MemoryError

u = u + alpha*p - это строка кода, которая терпит неудачу.

alpha является просто двойным, а u и r - это большие матрицы, описанные выше (оба одинакового размера).

Я не так сильно разбираюсь в ошибках памяти, особенно в Python. Любое понимание/советы в решении этого было бы очень оценено!

Спасибо

Ответы

Ответ 1

Перепишите на

p *= alpha
u += p

и это будет использовать гораздо меньше памяти. В то время как p = p*alpha выделяет целую новую матрицу для результата p*alpha, а затем отбрасывает старый p; p*= alpha делает то же самое на месте.

В общем случае с большими матрицами попробуйте использовать назначение op=.

Ответ 2

Еще один совет, который я нашел, чтобы избежать ошибок памяти, - это вручную сборка мусора. Когда объекты удаляются или выходят из области действия, память, используемая для этих переменных, не освобождается до тех пор, пока не будет выполнена сборка мусора. Я нашел с некоторыми из моего кода, используя большие массивы numpy, которые я получил MemoryError, но я могу избежать этого, если я вставляю вызовы в gc.collect() в соответствующих местах.

Вы должны изучить этот параметр только в том случае, если использование операторов стиля "op =" и т.д. не решает вашу проблему, так как это, вероятно, не самая лучшая практика кодирования во всех случаях вызова gc.collect().

Ответ 3

Ваша матрица имеет 288x288x156 = 12,939,264 записей, что для double может появиться до 400 МБ в памяти. numpy бросать a MemoryError на вас просто означает, что в функции, которую вы назвали памятью, необходимой для выполнения операции, не было доступно из ОС.

Если вы можете работать с разреженными матрицами, это может сэкономить вам много памяти.