2015-04-30 16 views
10

Obsługuję niektóre duże zbiory danych i robię co mogę, aby pozostać pod ograniczeniami pamięci R. Pojawiło się jedno pytanie dotyczące nadpisywania obiektów R. Mam duży obiekt data.table (lub dowolnego obiektu R), który musi być wielokrotnie kopiowany do tmp. Pytanie brzmi: czy robi to jakąś różnicę, jeśli usuwam tmp przed nadpisaniem? W kodzie:W jaki sposób zarządza się pamięcią podczas nadpisywania obiektów 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. 
} 

Załóżmy, że kopia jest konieczne (Gdybym dotrzeć do punktu, gdzie trzeba czytać very_large_data_table z dysku na każdej pętli, zrobię to, ale stoi pytanie: będzie żadnej różnicy na maksymalne użycie pamięci, jeśli jawnie usuwam v_l_d_t_tmp przed ponownym załadowaniem?).

Albo, aby nauczyć człowieka łowienia ryb, co mógłbym napisać (w R, nie wdawać się w ps), aby samemu odpowiedzieć na to pytanie?

To całkowicie OK, jeśli odpowiedź okaże się: "Zaufaj zbieraniu śmieci."

+0

Nie jest ekspertem, ale nie powinno to mieć znaczenia. W obu przypadkach oryginalna lokalizacja pamięci nie jest już wskazywana przez symbol, więc kwalifikuje się do zbierania śmieci (z przyjemnością poprawią ją eksperci). Jedną z rzeczy do rozważenia jest to, czy twoja 'data.table' naprawdę musi być skopiowana. Został zaprojektowany do modyfikacji przez odniesienie, więc nie musisz tego robić. – BrodieG

+2

Jako @BrodieG powiedział, że używając 'rm' mówi' R', że nie potrzebujesz już dostępu do 'v_l_d_t_tmp', a pamięć zajmowana przez tę tabelę staje się uprawniona do zbierania śmieci. Jednak odśmiecanie nie odbywa się, gdy wywołujesz 'rm', ale" automatycznie ", kiedy jest to konieczne. To nie zawsze działa dobrze, więc możesz wymusić odśmiecenie wywołując 'gc()' zaraz po wywołaniu 'rm (...)'. Może to spowodować, że twoja pętla zadziała. Jednak z mojego doświadczenia naprawdę trzeba zrestartować R, aby pamięć została prawidłowo wyczyszczona (co oznaczałoby czytanie w danych wejściowych dla każdej iteracji, prawdopodobnie dość powolne). – konvas

+0

Z własnego doświadczenia - truciciel zaufania. Przeanalizowaliśmy dane genomiczne i nadpisaliśmy wszystkie ramki danych przez nowe, ale nie mam teoretycznego zaplecza tego ... –

Odpowiedz

1

To jest komentarz bardziej niż odpowiedź, ale staje się on zbyt długi.

Domyślam się, że w tym przypadku połączenie z rm może być prawidłowe. Myślę, że począwszy od drugiej iteracji, możesz mieć 3 tabele w pamięci, jeśli nie zadzwonisz pod numer rm. Podczas kopiowania dużego obiektu, R nie może zwolnić pamięci zajmowanej przez v_l_d_t_tmp przed końcem kopii, ponieważ wywołanie funkcji może mieć błąd iw tym przypadku stary obiekt musi zostać zachowany. Rozważmy ten przykład:

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

Tutaj zdefiniowałem obiekt i funkcję, która zajmuje trochę czasu, aby coś zrobić. Jeśli spróbujesz:

x<-myfunc() 

i przerwać wykonywanie zanim się skończy „naturalnie”, obiekt x nadal istnieje, z jego treścią 1:10. Sądzę więc, że w twoim przypadku, nawet jeśli użyjesz tego samego symbolu, R nie może uwolnić swojej zawartości przed lub podczas kopiowania. Może to zrobić, jeśli usuniesz go przed następującą kopią. Oczywiście obiekt zostanie usunięty po skopiowaniu, ale może zabraknąć w nim pamięci.

Nie jestem ekspertem od wewnętrznych elementów R, więc nie przyjmuj za pewnik tego, co właśnie powiedziałem.

2

Oto kolejny pomysł ... nie odpowiada bezpośrednio na twoje pytanie, zamiast tego próbuje obejść go, eliminując problem z pamięcią w inny sposób. Może dostać myślisz:

Co jeśli zamiast buforować very_large_data_table, a następnie odczytać je tylko raz, zrobić co trzeba zrobić, a następnie wyjść R. Teraz napisać pętlę poza R i problem z pamięcią znika. To prawda, że ​​to kosztuje więcej procesora, ponieważ musisz czytać w 7 GB wiele razy ... ale może warto oszczędzić na kosztach pamięci. W rzeczywistości zmniejsza to o połowę zużycie pamięci, ponieważ nie trzeba już kopiować tabeli.

Poza tym, jak zauważyłem w komentarzach @konvas, również stwierdziłem, że rm() nawet z gc() nigdy nie dostarczył mi tego, czego potrzebowałem w długiej pętli, pamięć po prostu kumulowałaby się i w końcu ugrzęzła. Wyjście z R jest łatwym wyjściem.

musiałem to robić tak często, że pisałem pakiet mi pomóc przedmiotów cache tak: simpleCache

jeśli jesteś zainteresowany stara, to będzie wyglądać mniej więcej tak:

to zrobić poza R:

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

Następnie w R, to zrobić ... 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

To nie jest dobra wiadomość dla R, jeśli jest to właściwa odpowiedź. simpleCache wygląda świetnie, dzięki. – enfascination

Powiązane problemy