web-dev-qa-db-fra.com

Erreurs de mémoire et limites de la liste?

Je dois produire des matrices très grandes (très) (chaînes de Markov) à des fins scientifiques. J'effectue un calcul que je mets dans une liste de 20301 éléments (= une ligne de ma matrice). J'ai besoin de toutes ces données en mémoire pour procéder à la prochaine étape de Markov, mais je peux les stocker ailleurs (par exemple, un fichier) si nécessaire, même si cela ralentit le parcours de ma chaîne de Markov. Mon ordinateur (laboratoire scientifique): Bi-xénon 6 cœurs/12 unités chacun, mémoire de 12 Go, système d'exploitation: win64

  Traceback (most recent call last):
  File "my_file.py", line 247, in <module>
    ListTemp.append(calculus)
MemoryError

Exemple de résultats de calcul: 9.233747520008198e-102 (oui, c'est au-dessus de 1/9000)

L'erreur est déclenchée lors du stockage du 19766ème élément:

ListTemp[19766]
1.4509421012263216e-103

Si je vais plus loin

Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    ListTemp[19767]
IndexError: list index out of range

Donc, cette liste avait une erreur de mémoire à la boucle 19767.

Des questions:

  1. Y a-t-il une limite de mémoire dans une liste? S'agit-il d'une "limite par liste" ou d'une "limite globale par script"?

  2. Comment contourner ces limites? Des possibilités à l'esprit?

  3. Est-ce que ça va aider d'utiliser numpy, python64? Quelles sont les limites de la mémoire avec eux? Qu'en est-il des autres langues?

62
Taupi

Tout d’abord, voir Quelle taille peut un Python Array Get? et Numpy, problème avec les tableaux longs

Deuxièmement, la seule limite réelle vient de la quantité de mémoire dont vous disposez et de la façon dont votre système stocke les références de mémoire. Il n'y a pas de limite par liste, donc Python restera jusqu'à épuisement de la mémoire. Deux possibilités:

  1. Si vous utilisez un système d'exploitation plus ancien ou qui oblige les processus à utiliser une quantité de mémoire limitée, vous devrez peut-être augmenter la quantité de mémoire utilisée par le processus Python).
  2. Séparez la liste en utilisant la segmentation. Par exemple, créez les 1 000 premiers éléments de la liste, sélectionnez-les et enregistrez-les sur le disque, puis effectuez les 1 000 suivants. Pour les utiliser, désélectionnez un morceau à la fois afin de ne pas manquer de mémoire. C'est essentiellement la même technique que celle utilisée par les bases de données pour gérer plus de données que la RAM ne peut en contenir.
52

L'exception MemoryError que vous voyez est le résultat direct du manque de mémoire RAM disponible. Cela peut être dû à la limite de 2 Go par programme imposée par Windows ( programmes 32 bits ), ou au manque de mémoire disponible RAM sur votre ordinateur. (This lien est à une question précédente).

Vous devriez pouvoir étendre les 2 Go en utilisant une copie 64 bits de Python, à condition que vous utilisiez une copie 64 bits de Windows.

Le IndexError serait dû au fait que Python a frappé l'exception MemoryError avant de calculer le tableau entier. Là encore, il s'agit d'un problème de mémoire.

Pour résoudre ce problème, vous pouvez utiliser une copie 64 bits de Python ou, mieux encore, un moyen d'écrire vos résultats dans un fichier. Pour ce faire, regardez numpy tableaux mappés en mémoire .

Vous devriez pouvoir exécuter votre ensemble de calcul dans l’un de ces tableaux, car les données réelles seront écrites sur disque et seule une petite partie sera conservée en mémoire.

25
thomas

Il n'y a pas de limite de mémoire imposée par Python. Cependant, vous obtiendrez un MemoryError si vous manquez de RAM. vous dites que vous avez 20301 éléments dans le list. Cela semble trop petit pour provoquer une erreur de mémoire pour les types de données simples (par exemple, int), mais si chaque élément est un objet qui utilise beaucoup de mémoire, vous risquez de manquer de mémoire.

Le IndexError est toutefois probablement dû au fait que votre ListTemp n'a que 19767 éléments (indexés de 0 à 19766) et que vous essayez d'accéder au-delà du dernier élément.

Il est difficile de dire ce que vous pouvez faire pour éviter de dépasser la limite sans savoir exactement ce que vous essayez de faire. Utiliser numpy pourrait aider. Il semble que vous stockiez une quantité énorme de données. Il se peut que vous n’ayez pas besoin de tout stocker à chaque étape. Mais il est impossible de dire sans savoir.

7
MAK

Si vous souhaitez contourner ce problème, vous pouvez également utiliser l'étagère. Ensuite, vous créeriez des fichiers de la taille de la capacité de votre machine, et ne les placeriez que sur le RAM si nécessaire, en écrivant sur le disque dur et en récupérant les informations par morceaux peut le traiter.

Créez un fichier binaire et vérifiez si des informations s'y trouvent déjà. Si oui, créez une variable locale pour le conserver, sinon écrivez des données que vous jugez nécessaires.

Data = shelve.open('File01')
   for i in range(0,100):
     Matrix_Shelve = 'Matrix' + str(i)
     if Matrix_Shelve in Data:
        Matrix_local = Data[Matrix_Shelve]
     else:
        Data[Matrix_Selve] = 'somenthingforlater'

J'espère que cela ne semble pas trop arcaic.