Gestion de la mémoire R / impossible d'allouer un vecteur de taille n Mb

149

Je rencontre des problèmes en essayant d'utiliser des objets volumineux dans R. Par exemple:

> memory.limit(4000)
> a = matrix(NA, 1500000, 60)
> a = matrix(NA, 2500000, 60)
> a = matrix(NA, 3500000, 60)
Error: cannot allocate vector of size 801.1 Mb
> a = matrix(NA, 2500000, 60)
Error: cannot allocate vector of size 572.2 Mb # Can't go smaller anymore
> rm(list=ls(all=TRUE))
> a = matrix(NA, 3500000, 60) # Now it works
> b = matrix(NA, 3500000, 60)
Error: cannot allocate vector of size 801.1 Mb # But that is all there is room for

Je comprends que cela est lié à la difficulté d'obtenir des blocs de mémoire contigus (à partir d' ici ):

Les messages d'erreur commençant ne peut pas allouer de vecteur de taille indiquent un échec d'obtention de mémoire, soit parce que la taille a dépassé la limite d'espace d'adressage pour un processus ou, plus probablement, parce que le système n'a pas pu fournir la mémoire. Notez que sur une version 32 bits, il peut bien y avoir suffisamment de mémoire disponible, mais pas un bloc suffisamment grand d'espace d'adressage contigu pour le mapper.

Comment puis-je contourner cela? Ma principale difficulté est que j'arrive à un certain point de mon script et que R ne peut pas allouer 200-300 Mb pour un objet ... Je ne peux pas vraiment pré-allouer le bloc car j'ai besoin de mémoire pour d'autres traitements. Cela se produit même lorsque je supprime soigneusement les objets inutiles.

EDIT: Oui, désolé: Windows XP SP3, 4 Go de RAM, R 2.12.0:

> sessionInfo()
R version 2.12.0 (2010-10-15)
Platform: i386-pc-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=English_Caribbean.1252  LC_CTYPE=English_Caribbean.1252   
[3] LC_MONETARY=English_Caribbean.1252 LC_NUMERIC=C                      
[5] LC_TIME=English_Caribbean.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base
Benjamin
la source
Essayez d'utiliser «libre» pour désallouer la mémoire d'un autre processus non utilisé.
Manoel Galdino
5
@ Manoel Galdino: Qu'est-ce que «gratuit»? Une fonction R?
Benjamin
3
@Manoel: Dans R, la tâche de libérer de la mémoire est gérée par le garbage collector, pas par l'utilisateur. Si vous travaillez au niveau C, on peut manuellement Callocet Freemémoire, mais je soupçonne que ce n'est pas ce que fait Benjamin.
Sharpie
Dans la bibliothèque XML, vous pouvez utiliser gratuitement. Extrait de la documentation: "Cette fonction générique est disponible pour libérer explicitement la mémoire associée à l'objet donné. Elle est destinée à être utilisée sur des objets pointeurs externes qui n'ont pas de fonction / routine de finaliseur automatique qui nettoie la mémoire utilisée par le objet natif. "
Manoel Galdino

Réponses:

78

Déterminez si vous avez vraiment besoin de toutes ces données de manière explicite, ou la matrice peut-elle être clairsemée? Il existe un bon support dans R (voir le Matrixpackage pour par exemple) pour les matrices creuses.

Réduisez au minimum tous les autres processus et objets de R lorsque vous devez créer des objets de cette taille. Utilisez gc()pour effacer la mémoire maintenant inutilisée, ou mieux ne créez que l'objet dont vous avez besoin en une seule session .

Si ce qui précède ne peut pas vous aider, procurez-vous une machine 64 bits avec autant de RAM que vous pouvez vous le permettre et installez R 64 bits.

Si vous ne pouvez pas faire cela, il existe de nombreux services en ligne pour l'informatique à distance.

Si vous ne pouvez pas faire cela, les outils de mappage de mémoire comme package ff(ou bigmemorycomme Sascha le mentionne) vous aideront à créer une nouvelle solution. Dans mon expérience limitée ffest le package le plus avancé, mais vous devriez lire la High Performance Computingrubrique sur les vues de tâches CRAN.

mdsumner
la source
1
la tâche est la classification des images, avec randomForest. J'ai besoin d'une matrice des données d'entraînement (jusqu'à 60 bandes) et de 20 000 à 6 000 000 lignes pour alimenter randomForest. Actuellement, je dépasse environ 150 000 lignes car j'ai besoin d'un bloc contigu pour contenir l'objet randomForest résultant ... C'est aussi pourquoi bigmemory n'aide pas, car randomForest nécessite un objet matrice.
Benjamin
Qu'entendez-vous par "créer uniquement l'objet dont vous avez besoin en une seule session"?
Benjamin
ne créez un 'a' qu'une seule fois, si vous vous trompez la première fois, démarrez une nouvelle session
mdsumner
1
J'ajouterais que pour les programmes qui contiennent de grandes boucles où beaucoup de calcul est effectué mais la sortie est relativement petite, il peut être plus efficace en mémoire d'appeler la partie interne de la boucle via Rscript (à partir d'un script BASH ou Python) et collationnez / agrégez les résultats par la suite dans un autre script. De cette façon, la mémoire est complètement libérée après chaque itération. Il y a un peu de calcul gaspillé en rechargeant / recalculant les variables passées à la boucle, mais au moins vous pouvez contourner le problème de mémoire.
Benjamin
54

Pour les utilisateurs de Windows, ce qui suit m'a beaucoup aidé à comprendre certaines limitations de la mémoire:

  • avant d'ouvrir R, ouvrez le moniteur de ressources Windows (Ctrl-Alt-Suppr / Démarrer le gestionnaire de tâches / onglet Performances / cliquez sur le bouton du bas 'Moniteur de ressources' / onglet Mémoire)
  • vous verrez combien de mémoire RAM nous avons déjà utilisée avant d'ouvrir R, et par quelles applications. Dans mon cas, 1,6 Go sur un total de 4 Go sont utilisés. Je ne pourrai donc obtenir que 2,4 Go pour R, mais c'est maintenant le pire ...
  • ouvrez R et créez un ensemble de données de 1,5 Go, puis réduisez sa taille à 0,5 Go, le moniteur de ressources montre que ma RAM est utilisée à près de 95%.
  • utiliser gc()pour faire le ramasse-miettes => ça marche, je peux voir l'utilisation de la mémoire descendre à 2 Go

entrez la description de l'image ici

Conseil supplémentaire qui fonctionne sur ma machine:

  • préparer les entités, enregistrer en tant que fichier RData, fermer R, rouvrir R et charger les entités du train. Le gestionnaire de ressources affiche généralement une utilisation de la mémoire inférieure, ce qui signifie que même gc () ne récupère pas toute la mémoire possible et que la fermeture / réouverture de R fonctionne le mieux pour commencer avec la mémoire maximale disponible .
  • L'autre astuce consiste à charger uniquement le train pour l'entraînement (ne chargez pas le jeu de test, qui peut typiquement être la moitié de la taille du train). La phase d'entraînement peut utiliser la mémoire au maximum (100%), donc tout ce qui est disponible est utile. Tout cela est à prendre avec un grain de sel alors que j'expérimente les limites de mémoire R.
Timothée HENRY
la source
9
R fait le ramasse-miettes seul, ce gc()n'est qu'une illusion. La vérification du gestionnaire de tâches n'est qu'une opération très basique de Windows. Le seul conseil avec lequel je suis d'accord est l'enregistrement au format .RData
David Arenburg
3
@DavidArenburg gc () est une illusion? Cela signifierait que l'image que j'ai ci-dessus montrant la baisse de l'utilisation de la mémoire est une illusion. Je pense que vous vous trompez, mais je me trompe peut-être.
Timothée HENRY
4
Je ne voulais pas dire que gc()ça ne marche pas. Je veux juste dire que R le fait automatiquement, vous n'avez donc pas besoin de le faire manuellement. Voir ici
David Arenburg
2
@DavidArenburg Je peux vous dire avec certitude que la baisse d'utilisation de la mémoire dans l'image ci-dessus est due à la commande gc (). Je ne pense pas que le document que vous indiquez est correct, du moins pas pour ma configuration (Windows, R version 3.1.0 (2014-04-10) Plate-forme: i386-w64-mingw32 / i386 (32 bits)).
Timothée HENRY
15
Ok, pour la dernière fois. gc() FONCTIONNE . Vous n'avez tout simplement pas besoin de l'utiliser parce que R le fait en interne
David Arenburg
14

Le moyen le plus simple de contourner cette limitation est de passer à 64 bits R.

David Heffernan
la source
25
Ce n'est pas un remède en général - j'ai changé, et maintenant je l'ai à la Error: cannot allocate vector of size ... Gbplace (mais oui, j'ai beaucoup de données).
om-nom-nom
2
Peut-être pas un remède, mais cela aide beaucoup. Il suffit de charger la RAM et de continuer à augmenter memory.limit (). Ou peut-être pensez à partitionner / échantillonner vos données.
random_forest_fanatic
Si vous rencontrez des problèmes même en 64 bits, qui est essentiellement illimité, c'est probablement plus que vous essayez d'allouer quelque chose de vraiment massif. Avez-vous calculé la taille théorique du vecteur? Sinon, il se peut que votre ordinateur ait besoin de plus de RAM, mais vous ne pouvez en avoir que trop.
hangmanwa7id
bien d'essayer les solutions simples comme celle-ci avant d'autres solutions tête contre mur. Merci.
Nova
De plus, ce n'est pas exclusivement un problème avec Windows. J'utilise actuellement Ubuntu, 64 bits R, en utilisant Matrix, et j'ai des difficultés à manipuler un objet Matrix 20048 x 96448.
12

J'ai rencontré un problème similaire et j'ai utilisé 2 lecteurs flash comme «ReadyBoost». Les deux disques ont augmenté de 8 Go de mémoire supplémentaire (pour le cache) et ont résolu le problème et ont également augmenté la vitesse du système dans son ensemble. Pour utiliser Readyboost, faites un clic droit sur le lecteur, allez dans les propriétés et sélectionnez 'ReadyBoost' et sélectionnez le bouton radio 'utiliser cet appareil' et cliquez sur appliquer ou sur ok pour configurer.

Kwaku Damoah
la source
11

J'ai suivi la page d'aide de memor.limit et j'ai découvert que sur mon ordinateur, R par défaut peut utiliser jusqu'à ~ 1,5 Go de RAM et que l'utilisateur peut augmenter cette limite. En utilisant le code suivant,

>memory.limit()
[1] 1535.875
> memory.limit(size=1800)

m'a aidé à résoudre mon problème.

Rajib Kumar De
la source
1
Pourquoi cela est-il rejeté? Bien sûr, c'est une approche dangereuse, mais cela peut souvent aider si juste un peu plus de mémoire doit être allouée à la session pour qu'elle fonctionne.
Jeppe Olsen
3
Ce n'est qu'une solution spécifique à Windows
Jinhua Wang
9

Si vous exécutez votre script dans un environnement Linux, vous pouvez utiliser cette commande:

bsub -q server_name -R "rusage[mem=requested_memory]" "Rscript script_name.R"

et le serveur vous allouera la mémoire demandée (selon les limites du serveur, mais avec un bon serveur - des fichiers énormes peuvent être utilisés)

nurit
la source
1
Puis-je l'utiliser sur une instance Amazon EC2? Si oui, qu'est-ce que je mets à la place server_name? Je rencontre çacannot allocate vector size... en essayant de faire une énorme matrice de termes de document sur une AMI et je ne peux pas comprendre pourquoi il n'a pas assez de mémoire, ou combien je dois en louer. Je vous remercie!
seth127
Je suis un débutant Ubuntu et j'utilise Rstudio dessus. J'ai 16 Go de RAM. Comment appliquer le processus que vous montrez dans la réponse. Merci
runjumpfly
3

La méthode de sauvegarde / chargement mentionnée ci-dessus fonctionne pour moi. Je ne sais pas comment / si gc()défragmente la mémoire, mais cela semble fonctionner.

# defrag memory 
save.image(file="temp.RData")
rm(list=ls())
load(file="temp.RData")
Simon Woodward
la source