Python/Numpy 内存错误

26 投票
3 回答
75158 浏览
提问于 2025-04-16 07:50

基本上,我在用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只是一个双精度数,而ur都是上面提到的那种大矩阵(大小相同)。

我对Python中的内存错误了解不多。如果能给我一些解决这个问题的建议或见解,我会非常感激!

谢谢

3 个回答

7

你的矩阵有288x288x156=12,939,264个数据,这样的话,如果用double类型存储的话,可能会占用大约400MB的内存。numpy给你抛出一个MemoryError的错误,意思就是你调用的那个函数在运行时,操作所需的内存没有从操作系统那里得到。

如果你能使用稀疏矩阵,这样可能会节省很多内存。

12

我发现避免内存错误的另一个小窍门是手动控制垃圾回收。当一些对象被删除或者超出作用域时,这些变量占用的内存不会立即释放,直到进行垃圾回收。我在使用大型numpy数组的代码中遇到过内存错误(MemoryError),但如果在合适的地方插入gc.collect()的调用,就可以避免这个问题。

不过,只有在使用“op=”风格的操作符等方法无法解决问题时,才应该考虑这个选项,因为在代码中到处调用gc.collect()可能不是最好的编程习惯。

52

重写为

p *= alpha
u += p

这样做会使用更少的内存。因为 p = p*alpha 会为 p*alpha 的结果分配一个全新的矩阵,然后丢弃旧的 p; 而 p*= alpha 则是在原地进行同样的操作。

总的来说,对于大矩阵,尽量使用 op= 这种赋值方式。

撰写回答