2015-04-30 14 views
10

Sto gestendo alcuni set di dati di grandi dimensioni e sto facendo tutto il possibile per rispettare i limiti di memoria di R. Una domanda riguarda la sovrascrittura di oggetti R. Ho un grande data.table (o qualsiasi oggetto R), e deve essere copiato più volte su tmp. La domanda è: fa qualche differenza se cancello tmp prima di sovrascriverlo? In Codice:Come viene gestita la memoria durante la sovrascrittura degli oggetti R?

for (1:lots_of_times) { 
    v_l_d_t_tmp <- copy(very_large_data_table) # Necessary copy of 7GB data 
               # table on 16GB machine. I can 
               # afford 2 but not 3 copies. 
    ### do stuff to v_l_d_t_tmp and output 
    rm (v_l_d_t_tmp) # The question is whether this rm keeps max memory 
         # usage lower, or if it is equivalent to what an 
         # overwrite will automatically do on the next iteration. 
} 

Si supponga che la copia è necessario (se raggiungo un punto in cui ho bisogno di leggere very_large_data_table dal disco ad ogni ciclo, lo farò, ma la domanda sorge: ce la farà alcuna differenza su utilizzo massimo della memoria se elimini esplicitamente v_l_d_t_tmp prima di caricarlo nuovamente?).

Oppure, per insegnare all'uomo a pescare, cosa avrei potuto digitare (all'interno di R, non entriamo nello ps) per rispondere a me stesso?

È assolutamente OK se la risposta risulta essere: "Garbage collection affidabile".

+0

Non è un esperto, ma non dovrebbe fare la differenza. In entrambi i casi, la posizione di memoria originale non è più indicata da un simbolo, quindi è idonea per la garbage collection (felice di essere corretta dagli esperti). Una cosa da considerare è se il tuo 'data.table' ha davvero bisogno di essere copiato. È progettato per essere modificato in base al riferimento in modo da non doverlo fare. – BrodieG

+2

Come dice @BrodieG usando 'rm' dice a' R' che non è più necessario accedere a 'v_l_d_t_tmp' e la memoria occupata da questa tabella diventa idonea per la garbage collection. Tuttavia, la garbage collection non ha luogo quando chiamate 'rm', ma" automaticamente ", quando necessario. Questo non sempre funziona bene, quindi puoi forzare la garbage collection chiamando 'gc()' subito dopo aver chiamato 'rm (...)'. Questo potrebbe far funzionare il tuo loop. Tuttavia, secondo la mia esperienza, è necessario riavviare R affinché la memoria venga cancellata correttamente (il che significherebbe leggere gli input per ogni iterazione, probabilmente piuttosto lento). – konvas

+0

Dalla mia esperienza personale - confido Garbage Collector. Abbiamo analizzato i dati genomici e abbiamo sovrascritto tutti i frame di dati con quelli nuovi, ma non ho alcun background teorico a supporto ... –

risposta

1

Questo è un commento più che una risposta, ma sta diventando troppo lungo.

Immagino che in questo caso una chiamata a rm potrebbe essere corretta. Penso che partendo dalla seconda iterazione, potresti avere 3 tabelle in memoria se non chiami rm. Durante la copia dell'oggetto grande, R non può liberare la memoria occupata da v_l_d_t_tmp prima della fine della copia, poiché la chiamata alla funzione potrebbe avere un errore e in questo caso il vecchio oggetto deve essere conservato. Consideriamo questo esempio:

x<-1:10 
myfunc<-function(y) {Sys.sleep(3);30} 

Qui ho definito un oggetto e una funzione che richiede del tempo per fare qualcosa. Se si tenta:

x<-myfunc() 

e rompere l'esecuzione prima che finisca "naturalmente", l'oggetto x esiste ancora, con il suo contenuto 1:10. Quindi, suppongo che nel tuo caso, anche se usi lo stesso simbolo, R non può liberare il suo contenuto prima o durante la copia. Può se lo rimuovi prima della seguente copia. Ovviamente, l'oggetto verrà rimosso dopo la copia, ma potrebbe esaurirsi la memoria durante la copia.

Non sono affatto un esperto degli interni di R, quindi non dare per scontato quello che ho appena detto.

2

Ecco un'altra idea ... non risponde direttamente alla tua domanda, cerca invece di aggirarla eliminando il problema della memoria in un altro modo. Potrebbe farti pensare:

Che cosa se invece cache il very_large_data_table, e quindi leggere in una sola volta, fai quello che devi fare, e quindi uscire R. Ora, scrive un ciclo al di fuori di R, e la il problema della memoria scompare. Certo, questo ti costa più CPU perché devi leggere in 7GB più volte ... ma potrebbe valere la pena di risparmiare i costi della memoria. In effetti, questo dimezza l'uso della memoria, dal momento che non devi mai copiare il tavolo. Inoltre, come ho notato @konvas nei commenti, ho anche trovato che rm() anche con gc() non mi ha mai ottenuto quello che mi serviva con un ciclo lungo, la memoria si accumulava e alla fine si impantanava. Uscire da R è la via più facile.

ho dovuto fare questo così spesso che ho scritto un pacchetto per aiutarmi a oggetti di cache in questo modo: simpleCache

se siete interessati a provare, sarebbe simile a questa:

fare questo al di fuori della R:

for (1:lots_of_times) { 
Rscript my_script.R 
} 

Poi in R, fare questo ... my_script.R:

library(simpleCache) 
simpleCache("very_large_data_table", {r code for how 
you make this table }, assignTo="v_l_d_t_tmp") 

### do stuff to v_l_d_t_tmp and output 
+0

Non è una grande notizia per R se questa è la risposta giusta. simpleCache sembra fantastico, grazie. – enfascination