web-dev-qa-db-fra.com

Python / Numpy MemoryError

Fondamentalement, je reçois une erreur de mémoire dans python lorsque j'essaie d'effectuer une opération algébrique sur une matrice numpy. La variable u, est une grande matrice de double (dans l'échec cas c'est une matrice de doubles 288x288x156. Je n'obtiens cette erreur que dans ce cas énorme, mais je suis capable de le faire sur d'autres grandes matrices, mais pas aussi grandes). Voici l'erreur 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 est la ligne de code qui échoue.

alpha est juste un double, tandis que u et r sont les grandes matrices décrites ci-dessus (toutes deux de la même taille).

Je ne connais pas grand-chose aux erreurs de mémoire, en particulier en Python. Tout aperçu/conseils pour résoudre ce problème serait très apprécié!

Merci

24
tylerthemiler

Réécrire dans

p *= alpha
u += p

et cela utilisera beaucoup moins de mémoire. Tandis que p = p*alpha alloue une toute nouvelle matrice pour le résultat de p*alpha puis supprime l'ancien p; p*= alpha fait la même chose en place.

En général, avec de grandes matrices, essayez d'utiliser op= affectation.

50
luispedro

Une autre astuce que j'ai trouvée pour éviter les erreurs de mémoire est de contrôler manuellement garbage collection . Lorsque des objets sont supprimés ou sortent de notre portée, la mémoire utilisée pour ces variables n'est pas libérée jusqu'à ce qu'une récupération de place soit effectuée. J'ai trouvé avec une partie de mon code à l'aide de grands tableaux numpy que j'obtiens une erreur MemoryError, mais que je peux éviter cela si j'insère des appels à gc.collect () aux endroits appropriés.

Vous ne devriez étudier cette option que si l'utilisation d'opérateurs de style "op =", etc. ne résout pas votre problème car ce n'est probablement pas la meilleure pratique de codage d'avoir des appels à gc.collect () partout.

11
DaveP

Votre matrice a 288x288x156 = 12 939 264 entrées, ce qui pour double pourrait atteindre 400 Mo en mémoire. numpy lancer un MemoryError sur vous signifie simplement que dans la fonction que vous avez appelée, la mémoire nécessaire pour effectuer l'opération n'était pas disponible à partir du système d'exploitation.

Si vous pouvez travailler avec des matrices clairsemées, cela pourrait vous faire économiser beaucoup de mémoire.

7
Benjamin Bannier