Gerenciamento de memória R / não pode alocar vetor de tamanho n Mb

149

Estou com problemas ao tentar usar objetos grandes em R. Por exemplo:

> 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

Entendo que isso esteja relacionado à dificuldade de obter blocos contíguos de memória ( daqui ):

As mensagens de erro iniciadas não podem alocar vetor de tamanho indicam uma falha na obtenção de memória, porque o tamanho excedeu o limite de espaço de endereço para um processo ou, mais provavelmente, porque o sistema não conseguiu fornecer a memória. Observe que em uma compilação de 32 bits, pode haver bastante memória livre disponível, mas não um bloco contíguo de espaço de endereço grande o suficiente para mapear.

Como posso resolver isso? Minha principal dificuldade é que chego a um determinado ponto do meu script e R não pode alocar 200-300 Mb para um objeto ... Na verdade, não posso pré-alocar o bloco porque preciso da memória para outro processamento. Isso acontece mesmo quando eu removo objetos desnecessariamente desnecessariamente.

EDIT: Sim, desculpe: Windows XP SP3, 4Gb 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
fonte
Tente usar 'free' para desalocar a memória de outro processo não usado.
Manoel Galdino 02/03
5
@ Manoel Galdino: O que é 'grátis'? Uma função R?
Benjamin
3
@Manoel: No R, a tarefa de liberar memória é gerenciada pelo coletor de lixo, não pelo usuário. Se estiver trabalhando no nível C, pode-se manualmente Calloce com Freememória, mas suspeito que não é isso que Benjamin está fazendo.
Sharpie
Na biblioteca XML, você pode usar gratuitamente. Na documentação: "Esta função genérica está disponível para liberar explicitamente a memória associada ao objeto em questão. Destina-se ao uso em objetos ponteiros externos que não possuem uma função / rotina de finalização automática que limpa a memória usada pelo objeto objeto nativo ".
Manoel Galdino

Respostas:

78

Considere se você realmente precisa de todos esses dados explicitamente ou a matriz pode ser esparsa? Existe um bom suporte no R (veja o Matrixpacote para, por exemplo) para matrizes esparsas.

Mantenha todos os outros processos e objetos em R no mínimo quando precisar criar objetos desse tamanho. Use gc()para limpar a memória agora não utilizada ou, melhor ainda, crie o objeto necessário em uma sessão .

Se o exposto acima não puder ajudar, obtenha uma máquina de 64 bits com tanta RAM quanto você puder pagar e instale a R. de 64 bits.

Se você não puder fazer isso, existem muitos serviços online para computação remota.

Se você não puder fazer isso, as ferramentas de mapeamento de memória, como o pacote ff(ou bigmemorycomo Sascha menciona), ajudarão a criar uma nova solução. Na minha experiência limitada, ffestá o pacote mais avançado, mas você deve ler o High Performance Computingtópico em Exibições de tarefas do CRAN.

mdsumner
fonte
1
a tarefa é a classificação de imagens, com randomForest. Preciso ter uma matriz dos dados de treinamento (até 60 bandas) e de 20.000 a 6.000.000 de linhas para alimentar o randomForest. Atualmente, eu atingi o limite máximo de cerca de 150.000 linhas porque preciso de um bloco contíguo para armazenar o objeto randomForest resultante ... E também é por isso que bigmemory não ajuda, pois randomForest requer um objeto de matriz.
Benjamin
O que você quer dizer com "criar apenas o objeto necessário em uma sessão"?
Benjamin
apenas criam 'a' uma vez, se você errar a primeira vez que iniciar uma nova sessão
mdsumner
1
Eu acrescentaria que, para programas que contêm loops grandes em que é feita muita computação, mas a saída é relativamente pequena, pode ser mais eficiente em termos de memória chamar a parte interna do loop via Rscript (de um script BASH ou Python) e agrupe / agregue os resultados posteriormente em um script diferente. Dessa forma, a memória é completamente liberada após cada iteração. Há um pouco de computação desperdiçada ao recarregar / recalcular as variáveis ​​passadas para o loop, mas pelo menos você pode contornar o problema de memória.
Benjamin
54

Para usuários do Windows, o seguinte me ajudou bastante a entender algumas limitações de memória:

  • antes de abrir o R, abra o Windows Resource Monitor (Ctrl-Alt-Delete / Iniciar Gerenciador de Tarefas / guia Desempenho / clique no botão inferior 'Monitor de Recursos' / guia Memória)
  • você verá quanta memória RAM nós utilizamos antes de abrir o R ​​e por quais aplicativos. No meu caso, 1,6 GB do total de 4 GB são usados. Então, só conseguirei 2,4 GB para R, mas agora vem o pior ...
  • abra R e crie um conjunto de dados de 1,5 GB e reduza seu tamanho para 0,5 GB. O Monitor de Recursos mostra que minha RAM é usada em quase 95%.
  • usar gc()para fazer coleta de lixo => funciona, eu posso ver o uso da memória descer para 2 GB

insira a descrição da imagem aqui

Conselhos adicionais que funcionam na minha máquina:

  • prepare os recursos, salve como um arquivo RData, feche R, abra novamente R e carregue os recursos de trem. O Gerenciador de recursos normalmente mostra um uso mais baixo da memória, o que significa que mesmo o gc () não recupera toda a memória possível e o R / abrir / reabrir funciona melhor para começar com o máximo de memória disponível .
  • o outro truque é carregar apenas o conjunto de trem para treinamento (não carregue o conjunto de teste, que normalmente pode ser metade do tamanho do conjunto de trem). A fase de treinamento pode usar a memória ao máximo (100%), portanto, qualquer coisa disponível é útil. Tudo isso é necessário com um grão de sal enquanto estou experimentando os limites de memória R.
Timothée HENRY
fonte
9
R faz a coleta de lixo por si só, gc()é apenas uma ilusão. Verificar o Gerenciador de tarefas é apenas uma operação muito básica do Windows. O único conselho que posso concordar com está economizando em formato .rdata
David Arenburg
3
@DavidArenburg gc () é uma ilusão? Isso significaria que a imagem que tenho acima mostrando a queda do uso de memória é uma ilusão. Acho que você está errado, mas posso estar enganado.
Timothée HENRY
4
Eu não quis dizer que gc()isso não funciona. Eu só quero dizer que R faz isso automaticamente, então você não precisa fazê-lo manualmente. Veja aqui
David Arenburg
2
@DavidArenburg Posso dizer que a queda no uso de memória na figura acima se deve ao comando gc (). Não acredito que o documento para o qual você aponte esteja correto, pelo menos não para minha instalação (Windows, R versão 3.1.0 (10-04-2014)): i386-w64-mingw32 / i386 (32 bits)).
Timothée HENRY
15
Ok, pela última vez. gc() Funciona . Você só não precisa usá-lo porque R faz isso internamente
David Arenburg
14

A maneira mais simples de contornar essa limitação é alternar para 64 bits R.

David Heffernan
fonte
25
Isso não é uma cura em geral - eu mudei e agora mudei Error: cannot allocate vector of size ... Gb(mas sim, tenho muitos dados).
Om-nom-nom
2
Talvez não seja uma cura, mas ajuda muito. Basta carregar a RAM e continuar com o memory.limit (). Ou, talvez, pense em particionar / amostrar seus dados.
random_forest_fanatic
Se você está tendo problemas, mesmo em 64 bits, que é essencialmente ilimitado, provavelmente é mais do que você está tentando alocar algo realmente maciço. Você calculou qual o tamanho do vetor, teoricamente? Caso contrário, pode ser que seu computador precise de mais RAM, mas há muito que você pode ter.
precisa saber é o seguinte
É bom experimentar soluções simples como essa antes de mais soluções contra a parede. Obrigado.
Nova
Além disso, isso não é um problema exclusivo do Windows. Atualmente, estou executando o Ubuntu, R de 64 bits, usando Matrix e tendo dificuldade em manipular um objeto Matrix de 20048 x 96448.
12

Encontrei um problema semelhante e usei 2 unidades flash como 'ReadyBoost'. As duas unidades proporcionaram um aumento adicional de 8 GB de memória (para cache) e solucionaram o problema e também aumentaram a velocidade do sistema como um todo. Para usar o Readyboost, clique com o botão direito do mouse na unidade, vá para propriedades e selecione 'ReadyBoost' e selecione o botão de opção 'usar este dispositivo' e clique em Aplicar ou em OK para configurar.

Kwaku Damoah
fonte
11

Eu segui a página de ajuda do memor.limit e descobri que no meu computador o R, por padrão, pode usar até 1,5 GB de RAM e que o usuário pode aumentar esse limite. Usando o código a seguir,

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

me ajudou a resolver meu problema.

Rajib Kumar De
fonte
1
Por que isso está sendo rejeitado? com certeza, é uma abordagem perigosa, mas geralmente pode ajudar se for necessário alocar um pouco mais de memória para a sessão para que ela funcione.
Jeppe Olsen
3
Esta é apenas uma solução específica para Windows
Jinhua Wang
9

Se você estiver executando seu script no ambiente linux, poderá usar este comando:

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

e o servidor alocará a memória solicitada para você (de acordo com os limites do servidor, mas com um bom servidor - arquivos enormes podem ser usados)

nurit
fonte
1
Posso usar isso em uma instância do Amazon EC2? Se sim, do que coloco server_name? Estou enfrentando isso cannot allocate vector size...tentando fazer uma enorme Matriz de Termo de Documento em uma AMI e não consigo descobrir por que ela não tem memória suficiente ou quanto mais preciso alugar. Obrigado!
seth127
Eu sou iniciante no Ubuntu e estou usando o Rstudio nele. Eu tenho 16 GB de RAM. Como aplico o processo que você mostra na resposta. Graças
runjumpfly
3

O método salvar / carregar mencionado acima funciona para mim. Não sei como gc()desfragmentar a memória, mas isso parece funcionar.

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