Triki zarządzania dostępną pamięcią w sesji R

Jakich sztuczek używają ludzie do zarządzania dostępną pamięcią interaktywnej sesji R? Używam funkcji poniżej [na podstawie postów Petra Pikala i Davida Hindsa do listy r-help w 2004], aby wylistować (i / lub sortować) największe obiekty i czasami rm() Niektóre z nich. Ale zdecydowanie najskuteczniejszym rozwiązaniem było ... do uruchomienia Pod 64-bitowym Linuksem z dużą ilością pamięci.

Jakieś inne fajne sztuczki, którymi ludzie chcieliby się podzielić? Jeden na post, proszę.
# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.size <- napply(names, object.size)
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size, obj.dim)
    names(out) <- c("Type", "Size", "Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
    if (head)
        out <- head(out, n)
    out
}
# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}
Author: user227710, 2009-08-31

27 answers

Upewnij się, że nagrywasz swoją pracę w powtarzalnym skrypcie. Od czasu do czasu otwórz ponownie R, a następnie source() Twój skrypt. Wyczyścisz wszystko, czego już nie używasz, a dodatkową korzyścią będzie przetestowanie Twojego kodu.

 203
Author: hadley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-31 16:09:59

Używam danych .Tabela Pakiet. Za pomocą operatora := można:

  • Dodaj kolumny według referencji
  • Modyfikuj podzbiory istniejących kolumn według referencji i według grup według referencji
  • Delete columns by reference

Żadna z tych operacji nie kopiuje (potencjalnie dużej) data.table w ogóle, ani razu.

  • agregacja jest również szczególnie szybka, ponieważ data.table zużywa znacznie mniej pamięci roboczej.

Powiązane linki :

 165
Author: Matt Dowle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:10

Widziałem to na Twitterze i myślę, że to niesamowita funkcja Dirka! Idąc dalej od odpowiedzi JD Longa, zrobiłbym to dla przyjaznego dla użytkownika czytania:

# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.prettysize <- napply(names, function(x) {
                           format(utils::object.size(x), units = "auto") })
    obj.size <- napply(names, object.size)
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
    names(out) <- c("Type", "Size", "PrettySize", "Length/Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
    if (head)
        out <- head(out, n)
    out
}

# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

lsos()

Co skutkuje czymś w rodzaju:

                      Type   Size PrettySize Length/Rows Columns
pca.res                 PCA 790128   771.6 Kb          7      NA
DF               data.frame 271040   264.7 Kb        669      50
factor.AgeGender   factanal  12888    12.6 Kb         12      NA
dates            data.frame   9016     8.8 Kb        669       2
sd.                 numeric   3808     3.7 Kb         51      NA
napply             function   2256     2.2 Kb         NA      NA
lsos               function   1944     1.9 Kb         NA      NA
load               loadings   1768     1.7 Kb         12       2
ind.sup             integer    448  448 bytes        102      NA
x                 character     96   96 bytes          1      NA

Uwaga: główna część, którą dodałem była (ponownie, zaadaptowana z odpowiedzi JD):

obj.prettysize <- napply(names, function(x) {
                           print(object.size(x), units = "auto") })
 115
Author: Tony Breyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-26 14:53:25

Agresywnie wykorzystuję parametr subset z wyborem tylko wymaganych zmiennych podczas przekazywania ramek danych do argumentu data= funkcji regresji. Powoduje to pewne błędy, jeśli zapomnę dodać zmienne zarówno do formuły, jak i wektora select=, ale nadal oszczędza dużo czasu z powodu zmniejszenia kopiowania obiektów i znacznie zmniejsza ślad pamięci. Powiedzmy, że mam 4 miliony płyt ze 110 zmiennymi (I mam.) Przykład:

# library(rms); library(Hmisc) for the cph,and rcs functions
Mayo.PrCr.rbc.mdl <- 
cph(formula = Surv(surv.yr, death) ~ age + Sex + nsmkr + rcs(Mayo, 4) + 
                                     rcs(PrCr.rat, 3) +  rbc.cat * Sex, 
     data = subset(set1HLI,  gdlab2 & HIVfinal == "Negative", 
                           select = c("surv.yr", "death", "PrCr.rat", "Mayo", 
                                      "age", "Sex", "nsmkr", "rbc.cat")
   )            )

Poprzez ustawienie kontekst i strategia: zmienna gdlab2 jest wektorem logicznym, który został skonstruowany dla osób w zbiorze danych, który miał wszystkie normalne lub prawie normalne wartości dla kilku testów laboratoryjnych i HIVfinal był wektorem znaków, który podsumował wstępne i potwierdzające testy na HIV.

 50
Author: IRTFM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-15 17:07:44

Uwielbiam skrypt Dirka. LS. objects (), ale ciągle mrużyłem oczy, aby policzyć znaki w kolumnie rozmiar. Więc zrobiłem kilka brzydkich hacków, aby prezentował się z ładnym formatowaniem dla rozmiaru:

.ls.objects <- function (pos = 1, pattern, order.by,
                        decreasing=FALSE, head=FALSE, n=5) {
    napply <- function(names, fn) sapply(names, function(x)
                                         fn(get(x, pos = pos)))
    names <- ls(pos = pos, pattern = pattern)
    obj.class <- napply(names, function(x) as.character(class(x))[1])
    obj.mode <- napply(names, mode)
    obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
    obj.size <- napply(names, object.size)
    obj.prettysize <- sapply(obj.size, function(r) prettyNum(r, big.mark = ",") )
    obj.dim <- t(napply(names, function(x)
                        as.numeric(dim(x))[1:2]))
    vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
    obj.dim[vec, 1] <- napply(names, length)[vec]
    out <- data.frame(obj.type, obj.size,obj.prettysize, obj.dim)
    names(out) <- c("Type", "Size", "PrettySize", "Rows", "Columns")
    if (!missing(order.by))
        out <- out[order(out[[order.by]], decreasing=decreasing), ]
        out <- out[c("Type", "PrettySize", "Rows", "Columns")]
        names(out) <- c("Type", "Size", "Rows", "Columns")
    if (head)
        out <- head(out, n)
    out
}
 48
Author: JD Long,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 15:59:45

To dobra sztuczka.

Inną sugestią jest używanie obiektów wydajnych w pamięci wszędzie tam, gdzie to możliwe: na przykład, użyj matrycy zamiast danych.rama.

To tak naprawdę nie dotyczy zarządzania pamięcią, ale jedną z ważnych funkcji, która nie jest powszechnie znana, jest pamięć.limit (). Możesz zwiększyć wartość domyślną za pomocą tego polecenia, pamięć.limit (size=2500), gdzie rozmiar jest w MB. Jak wspomniał Dirk, trzeba używać 64-bitów, aby naprawdę z tego skorzystać.

 34
Author: Shane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-31 19:08:45

Bardzo podoba mi się ulepszona funkcja obiektów opracowana przez Dirka. Przez większość czasu wystarcza mi bardziej podstawowe wyjście z nazwą i rozmiarem obiektu. Oto prostsza funkcja o podobnym celu. Użycie pamięci może być uporządkowane alfabetycznie lub według rozmiaru, może być ograniczone do określonej liczby obiektów i może być uporządkowane rosnąco lub malejąco. Ponadto często pracuję z danymi, które są 1GB+, więc funkcja zmienia jednostki odpowiednio.

showMemoryUse <- function(sort="size", decreasing=FALSE, limit) {

  objectList <- ls(parent.frame())

  oneKB <- 1024
  oneMB <- 1048576
  oneGB <- 1073741824

  memoryUse <- sapply(objectList, function(x) as.numeric(object.size(eval(parse(text=x)))))

  memListing <- sapply(memoryUse, function(size) {
        if (size >= oneGB) return(paste(round(size/oneGB,2), "GB"))
        else if (size >= oneMB) return(paste(round(size/oneMB,2), "MB"))
        else if (size >= oneKB) return(paste(round(size/oneKB,2), "kB"))
        else return(paste(size, "bytes"))
      })

  memListing <- data.frame(objectName=names(memListing),memorySize=memListing,row.names=NULL)

  if (sort=="alphabetical") memListing <- memListing[order(memListing$objectName,decreasing=decreasing),] 
  else memListing <- memListing[order(memoryUse,decreasing=decreasing),] #will run if sort not specified or "size"

  if(!missing(limit)) memListing <- memListing[1:limit,]

  print(memListing, row.names=FALSE)
  return(invisible(memListing))
}

A oto przykład Wyjście:

> showMemoryUse(decreasing=TRUE, limit=5)
      objectName memorySize
       coherData  713.75 MB
 spec.pgram_mine  149.63 kB
       stoch.reg  145.88 kB
      describeBy    82.5 kB
      lmBandpass   68.41 kB
 33
Author: Michael Hallquist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-23 13:21:49

Nigdy nie zapisuję przestrzeni roboczej R. Używam skryptów importu i skryptów danych i wypisuję wszystkie szczególnie duże obiekty danych, których nie chcę często odtwarzać do plików. W ten sposób zawsze zaczynam od świeżego obszaru roboczego i nie muszę czyścić dużych obiektów. To bardzo miła funkcja.

 30
Author: kpierce8,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-31 21:45:21

Niestety nie miałem czasu, aby przetestować go intensywnie, ale tutaj jest wskazówka pamięci, że nie widziałem wcześniej. Dla mnie Wymagana pamięć została zmniejszona o ponad 50%. Kiedy czytasz rzeczy w R z na przykład czytać.csv wymagają pewnej ilości pamięci. Następnie możesz je zapisać za pomocą save("Destinationfile",list=ls()) Przy następnym otwarciu R możesz użyć load("Destinationfile") Teraz zużycie pamięci może się zmniejszyć. Byłoby miło, gdyby ktoś mógł potwierdzić, czy daje to podobne wyniki z innym zestaw danych.

 30
Author: Dennis Jaheruddin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-07 09:37:35

Aby jeszcze bardziej zilustrować wspólną strategię częstych restartów, możemy użyć littler , który pozwala nam uruchamiać proste wyrażenia bezpośrednio z wiersza poleceń. Oto przykład, którego czasami używam do czasu różnych BLAS dla prostego crossprod.

 r -e'N<-3*10^3; M<-matrix(rnorm(N*N),ncol=N); print(system.time(crossprod(M)))'

Podobnie,

 r -lMatrix -e'example(spMatrix)'

Ładuje Pakiet macierzy (poprzez przełącznik --packages | -l) i uruchamia przykłady funkcji spMatrix. Ponieważ r zawsze zaczyna "świeże", ta metoda jest również dobrym testem podczas pakietu rozwój.

Last but not least r również świetnie sprawdza się w automatycznym trybie wsadowym w skryptach przy użyciu '#!/ usr / bin / r ' shebang-header. Rscript jest alternatywą, w której littler jest niedostępny (np. w Windows).

 27
Author: Dirk Eddelbuettel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-31 22:26:15

Zarówno dla szybkości, jak i pamięci, podczas budowania dużej ramki danych za pomocą skomplikowanej serii kroków, okresowo przepuszczam ją (budowany zestaw danych w toku) na dysk, dołączając do wszystkiego, co było wcześniej, a następnie restartuję ją. W ten sposób kroki pośrednie działają tylko na małych ramkach danych (co jest dobre, ponieważ np. rbind spowalnia znacznie przy większych obiektach). Cały zestaw danych można odczytać z powrotem pod koniec procesu, gdy wszystkie pośrednie obiekty zostały usunięte.

dfinal <- NULL
first <- TRUE
tempfile <- "dfinal_temp.csv"
for( i in bigloop ) {
    if( !i %% 10000 ) { 
        print( i, "; flushing to disk..." )
        write.table( dfinal, file=tempfile, append=!first, col.names=first )
        first <- FALSE
        dfinal <- NULL   # nuke it
    }

    # ... complex operations here that add data to 'dfinal' data frame  
}
print( "Loop done; flushing to disk and re-reading entire data set..." )
write.table( dfinal, file=tempfile, append=TRUE, col.names=FALSE )
dfinal <- read.table( tempfile )
 23
Author: Ben B-L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-01 14:52:09

Tylko zauważ, że data.table Pakiet tables() wydaje się być całkiem dobrym zamiennikiem dla .ls.objects() niestandardowej funkcji Dirka (opisanej we wcześniejszych odpowiedziach), chociaż tylko dla danych.ramki / tabele a nie np. macierze, tablice, listy.

 17
Author: geotheory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-11 10:59:54
  1. Mam szczęście i moje duże zbiory danych są zapisywane przez instrument w "kawałkach" (podzbiorach) około 100 MB (32-bitowy binarny). W ten sposób mogę wykonać etapy wstępnego przetwarzania (usuwanie niedoinformowanych części, downsampling) sekwencyjnie przed połączeniem zestawu danych.

  2. Wywołanie gc () "ręcznie" może pomóc, jeśli rozmiar danych zbliży się do dostępnej pamięci.

  3. Czasami inny algorytm potrzebuje znacznie mniej pamięci.
    Czasami jest wymiana między wektoryzacja i wykorzystanie pamięci.
    porównaj: split & lapply vs.pętla for.

  4. Ze względu na szybką i łatwą analizę danych, często pracuję najpierw z małym losowym podzbiorem (sample ()) danych. Po skrypcie analizy danych/.Rnw jest gotowy kod analizy danych, a pełne dane trafiają do serwera obliczeń w ciągu nocy / w ciągu weekendu/... obliczenia.

 16
Author: cbeleites unhappy with SX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-22 13:23:51

Użycie środowisk zamiast list do obsługi kolekcji obiektów, które zajmują znaczną ilość pamięci roboczej.

Powód: za każdym razem, gdy element struktury list jest modyfikowany, cała lista jest tymczasowo powielana. Staje się to problemem, jeśli zapotrzebowanie na pamięć na liście wynosi około połowy dostępnej pamięci roboczej, ponieważ wtedy dane muszą zostać zamienione na wolny dysk twardy. Środowiska, z drugiej strony, nie podlegają temu zachowaniu i mogą być traktowane podobnie jak listy.

Oto przykład:

get.data <- function(x)
{
  # get some data based on x
  return(paste("data from",x))
}

collect.data <- function(i,x,env)
{
  # get some data
  data <- get.data(x[[i]])
  # store data into environment
  element.name <- paste("V",i,sep="")
  env[[element.name]] <- data
  return(NULL)  
}

better.list <- new.env()
filenames <- c("file1","file2","file3")
lapply(seq_along(filenames),collect.data,x=filenames,env=better.list)

# read/write access
print(better.list[["V1"]])
better.list[["V2"]] <- "testdata"
# number of list elements
length(ls(better.list))

W połączeniu ze strukturami takimi jak big.matrix lub data.table, które pozwalają na zmianę ich zawartości na miejscu, można osiągnąć bardzo efektywne wykorzystanie pamięci.

 11
Author: Georg Schnabel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-06 10:47:59

Funkcja ll w pakiecie gData może również pokazywać wykorzystanie pamięci każdego obiektu.

gdata::ll(unit='MB')
 8
Author: user1436187,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-22 20:58:57

Jeśli naprawdę chcesz uniknąć przecieków, powinieneś unikać tworzenia dużych obiektów w globalnym środowisku.

To, co zwykle robię, to mieć funkcję, która wykonuje zadanie i zwraca NULL - wszystkie dane są odczytywane i manipulowane w tej funkcji lub innych, które wywołuje.

 7
Author: Alexander Radev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-20 06:34:16

Z tylko 4GB PAMIĘCI RAM (z systemem Windows 10, więc zrób to około 2 lub bardziej realistycznie 1GB) musiałem być bardzo ostrożny z alokacją.

Używam danych.stół prawie wyłącznie.

Funkcja 'fread' pozwala na podzestaw informacji według nazw pól podczas importu; importuje tylko pola, które są rzeczywiście potrzebne na początek. Jeśli używasz base R read, null fałszywych kolumn natychmiast po imporcie.

As 42- sugeruje, gdzie kiedykolwiek to możliwe będę następnie podzbiór w kolumnach natychmiast po zaimportowaniu informacji.

Często rm () obiekty ze środowiska, gdy tylko nie są już potrzebne, np. w następnej linii po użyciu ich do podzbioru czegoś innego i wywołania gc ().

'fread' i 'fwrite' z danych.tabela może być bardzo Szybka w porównaniu z bazą r czyta i zapisuje.

Jak sugerujekpierce8 , prawie zawsze fwrite wszystko z otoczenia i fread it back In, nawet z tysiącami / setkami tysięcy małych plików do przejrzenia. To nie tylko utrzymuje środowisko "czyste" i utrzymuje alokację pamięci na niskim poziomie, ale prawdopodobnie ze względu na poważny brak dostępnej pamięci RAM, R ma skłonność do częstych awarii na moim komputerze; naprawdę często. Posiadanie kopii zapasowej informacji na samym dysku, gdy kod przechodzi przez różne etapy, oznacza, że nie muszę zaczynać od początku, jeśli ulegnie awarii.

Od 2017 roku, myślę, że najszybsze dyski SSD działają około kilku GB na sekundę przez port M2. Mam naprawdę podstawowy dysk SSD 50GB Kingston V300 (550MB/s), którego używam jako mojego dysku podstawowego(ma Windows i R na nim). Wszystkie informacje przechowuję na tanim talerzu WD 500GB. Przenoszę zestawy danych na dysk SSD, gdy zaczynam nad nimi pracować. To, w połączeniu z "fread" i "fwrite" wszystko działa świetnie. Próbowałem użyć 'ff', ale wolę ten pierwszy. Prędkość odczytu/zapisu 4K może powodować problemy z tym; tworzenie kopii zapasowej ćwierć miliona plików 1k (o wartości 250 MB) z dysku SSD na talerz może zająć wiele godzin. O ile mi wiadomo, nie ma jeszcze żadnego pakietu R, który mógłby automatycznie zoptymalizować proces "chunkification"; np. sprawdzić, ile pamięci RAM ma użytkownik, przetestować prędkość odczytu/zapisu pamięci RAM / wszystkich podłączonych dysków, a następnie zasugerować optymalny protokół "chunkification". Może to spowodować znaczące ulepszenia przepływu pracy / optymalizację zasobów; np. podzielić go na ... MB na ram - > split to do ... MB na SSD - > podziel na.. MB na talerzu - > podziel na.. MB na taśmie. Może wcześniej pobrać zestawy danych, aby nadać mu bardziej realistyczny wskaźnik do pracy.

Wiele problemów, nad którymi pracowałem w R, wiąże się z tworzeniem par kombinacji i permutacji, potrójnych itp., co sprawia, że ograniczanie pamięci RAM jest bardziej ograniczeniem, ponieważ częstoprzynajmniej wykładniczo rozszerza się w pewnym momencie. To sprawiło, że skupiłem wiele uwagi na jakośćw przeciwieństwie do Ilość informacji wchodzącej do nich na początek, zamiast próbować je potem wyczyścić, oraz sekwencja operacji w przygotowaniu informacji na początek (zaczynając od najprostszej operacji i zwiększając złożoność); np. podzbiór, następnie merge / join, następnie tworzą kombinacje / permutacje itp.

Wydaje się, że korzystanie z bazy r odczytu i zapisu w niektórych przypadkach przynosi pewne korzyści. Na przykład wykrywanie błędów w "fread" jest tak dobry, że może być trudno próbować dostać naprawdę brudne informacje do R, aby zacząć je czyścić. Base R również wydaje się być dużo łatwiejsze, jeśli używasz Linuksa. Base R wydaje się działać dobrze w Linuksie, Windows 10 używa ~20GB miejsca na dysku, podczas gdy Ubuntu potrzebuje tylko kilka GB, PAMIĘĆ RAM potrzebna w Ubuntu jest nieco niższa. Ale zauważyłem dużą ilość ostrzeżeń i błędów podczas instalowania pakietów innych firm w (L) Ubuntu. Nie polecam dryfowania zbyt daleko od (L) Ubuntu lub inne dystrybucje stockowe z Linuksem, ponieważ można stracić tyle ogólnej kompatybilności, że czyni proces prawie bezcelowym(myślę ,że 'unity' ma zostać anulowane w Ubuntu od 2017). Zdaję sobie sprawę, że to nie pójdzie dobrze z niektórymi użytkownikami Linuksa, ale niektóre niestandardowe dystrybucje są bezcelowe poza nowością (spędziłem lata używając samego Linuksa).

Mam nadzieję, że niektóre z nich mogą pomóc innym.

 7
Author: bg49ag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-06 03:00:17

To nic nie dodaje do powyższego, ale jest napisane w prostym i mocno skomentowanym stylu, który lubię. Daje tabelę z obiektami uporządkowanymi w rozmiarze, ale bez niektórych szczegółów podanych w powyższych przykładach:

#Find the objects       
MemoryObjects = ls()    
#Create an array
MemoryAssessmentTable=array(NA,dim=c(length(MemoryObjects),2))
#Name the columns
colnames(MemoryAssessmentTable)=c("object","bytes")
#Define the first column as the objects
MemoryAssessmentTable[,1]=MemoryObjects
#Define a function to determine size        
MemoryAssessmentFunction=function(x){object.size(get(x))}
#Apply the function to the objects
MemoryAssessmentTable[,2]=t(t(sapply(MemoryAssessmentTable[,1],MemoryAssessmentFunction)))
#Produce a table with the largest objects first
noquote(MemoryAssessmentTable[rev(order(as.numeric(MemoryAssessmentTable[,2]))),])
 5
Author: JamesF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-26 11:55:40

To jest nowsza odpowiedź na to doskonałe stare pytanie. Z Zaawansowanego R Hadleya:

install.packages("pryr")

library(pryr)

object_size(1:10)
## 88 B

object_size(mean)
## 832 B

object_size(mtcars)
## 6.74 kB

(http://adv-r.had.co.nz/memory.html )

 5
Author: Chris Beeley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-23 18:01:51

Jeśli pracujesz na Linuksie i chcesz używać kilku procesów i musisz tylko wykonać odczyt operacji na jednym lub więcej dużych obiektach Użyj makeForkCluster zamiast makePSOCKcluster. Oszczędza to również czas wysyłania dużego obiektu do innych procesów.

 3
Author: gdkrmr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-22 16:10:27

Naprawdę doceniam niektóre z powyższych odpowiedzi, podążając za @ hadley i @ Dirk, które sugerują zamknięcie R i wydanie source i używając linii poleceń wymyślam rozwiązanie, które działało bardzo dobrze dla mnie. Miałem do czynienia z setkami widm masowych, każde zajmuje około 20 Mb pamięci, więc użyłem dwóch skryptów R, w następujący sposób: {]}

Najpierw opakowanie:

#!/usr/bin/Rscript --vanilla --default-packages=utils

for(l in 1:length(fdir)) {

   for(k in 1:length(fds)) {
     system(paste("Rscript runConsensus.r", l, k))
   }
}

Za pomocą tego skryptu w zasadzie kontroluję co robi mój skrypt główny runConsensus.r i zapisuję odpowiedź na dane wyjściowe. Z tym, każdy kiedy wrapper wywoĹ ' a skrypt wydaje siÄ™, Ĺźe R jest ponownie otwarty i pamiÄ ™ Ä ‡ jest zwolniona.

Mam nadzieję, że to pomoże.
 2
Author: user1265067,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 12:25:49

Jak również bardziej ogólne techniki zarządzania pamięcią podane w powyższych odpowiedziach, zawsze staram się zmniejszyć rozmiar moich obiektów w miarę możliwości. Na przykład pracuję z bardzo dużymi, ale bardzo rzadkimi macierzami, innymi słowy macierzami, w których większość wartości jest równa zeru. Korzystając z pakietu 'Matrix' (ważna kapitalizacja) udało mi się zredukować średnie rozmiary obiektów z ~2GB do ~200Mb tak po prostu:

my.matrix <- Matrix(my.matrix)

Pakiet Matrix zawiera formaty danych, które mogą być używane dokładnie tak, jak zwykłe macierze (nie trzeba zmieniać innego kodu), ale są w stanie przechowywać rzadkie dane znacznie wydajniej, niezależnie od tego, czy są ładowane do pamięci, czy zapisywane na dysku.

Dodatkowo otrzymywane pliki raw są w formacie 'long', gdzie każdy punkt danych ma zmienne x, y, z, i. Znacznie bardziej wydajne jest przekształcanie danych w tablicę wymiarów x * y * z z tylko zmienną i.

Poznaj swoje dane i użyj odrobiny zdrowego rozsądku.
 2
Author: D Greenwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 15:30:19

Wskazówka dotycząca obsługi obiektów wymagających ciężkich obliczeń pośrednich: podczas korzystania z obiektów, które wymagają wielu ciężkich obliczeń i pośrednich kroków do utworzenia, często uważam za przydatne napisać fragment kodu z funkcją do utworzenia obiektu, a następnie oddzielny fragment kodu, który daje mi możliwość wygenerowania i zapisania obiektu jako pliku rmd lub załadować go zewnętrznie z pliku rmd, który już wcześniej zapisałem. Jest to szczególnie łatwe do zrobienia w R Markdown używając poniższej struktury kodu.

```{r Create OBJECT}

COMPLICATED.FUNCTION <- function(...) { Do heavy calculations needing lots of memory;
                                        Output OBJECT; }

```
```{r Generate or load OBJECT}

LOAD <- TRUE;
#NOTE: Set LOAD to TRUE if you want to load saved file
#NOTE: Set LOAD to FALSE if you want to generate and save

if(LOAD == TRUE) { OBJECT <- readRDS(file = 'MySavedObject.rds'); } else
                 { OBJECT <- COMPLICATED.FUNCTION(x, y, z);
                             saveRDS(file = 'MySavedObject.rds', object = OBJECT); }

```

Z tą strukturą kodu, wszystko, co muszę zrobić, to zmienić LOAD w zależności od tego, czy chcę wygenerować i zapisać obiekt, czy załadować go bezpośrednio z istniejącego zapisanego pliku. (Oczywiście muszę go wygenerować i zapisać za pierwszym razem, ale po tym mam możliwość wczytania go.) Ustawienie LOAD = TRUE omija korzystanie z mojej skomplikowanej funkcji i unika wszystkich ciężkich obliczeń w niej. Ta metoda nadal wymaga wystarczającej ilości pamięci do przechowywania obiekt zainteresowania, ale oszczędza ci to od konieczności obliczania go za każdym razem, gdy uruchamiasz kod. W przypadku obiektów, które wymagają dużo ciężkich obliczeń etapów pośrednich (np. w przypadku obliczeń obejmujących pętle na dużych tablicach) może to zaoszczędzić znaczną ilość czasu i obliczeń.

 2
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-14 00:32:39

Running

for (i in 1:10) 
    gc(reset = T)

Od czasu do czasu pomaga R uwolnić nieużywaną, ale wciąż nie zwolnioną pamięć.

 1
Author: Marcelo Ventura,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-20 04:41:52

Możesz również uzyskać pewne korzyści używając knitr i wkładając swój skrypt w RMD chuncks.

Zazwyczaj dzielę kod na różne części i wybieram, który z nich zapisze punkt kontrolny w pamięci podręcznej lub w pliku RDS, i

Tam możesz ustawić fragment do zapisania w "pamięci podręcznej", lub możesz zdecydować się na uruchomienie lub nie konkretnego fragmentu. W ten sposób w pierwszym uruchomieniu można przetworzyć tylko "part 1", w innym wykonaniu można wybrać tylko" part 2", itd.

Przykład:

part1
```{r corpus, warning=FALSE, cache=TRUE, message=FALSE, eval=TRUE}
corpusTw <- corpus(twitter)  # build the corpus
```
part2
```{r trigrams, warning=FALSE, cache=TRUE, message=FALSE, eval=FALSE}
dfmTw <- dfm(corpusTw, verbose=TRUE, removeTwitter=TRUE, ngrams=3)
```

Jako efekt uboczny, to również może zaoszczędzić kilka bólów głowy pod względem powtarzalności:)

 1
Author: Matias Thayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-16 14:47:41

Na podstawie odpowiedzi @ Dirka i @ Tony ' ego zrobiłem małą aktualizację. Wynik był wyprowadzany [1] przed wartościami pretty size, więc wyjąłem capture.output, które rozwiązały problem:

.ls.objects <- function (pos = 1, pattern, order.by,
                     decreasing=FALSE, head=FALSE, n=5) {
napply <- function(names, fn) sapply(names, function(x)
    fn(get(x, pos = pos)))
names <- ls(pos = pos, pattern = pattern)
obj.class <- napply(names, function(x) as.character(class(x))[1])
obj.mode <- napply(names, mode)
obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
obj.prettysize <- napply(names, function(x) {
    format(utils::object.size(x),  units = "auto") })
obj.size <- napply(names, utils::object.size)

obj.dim <- t(napply(names, function(x)
    as.numeric(dim(x))[1:2]))
vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
obj.dim[vec, 1] <- napply(names, length)[vec]
out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
names(out) <- c("Type", "Size", "PrettySize", "Rows", "Columns")
if (!missing(order.by))
    out <- out[order(out[[order.by]], decreasing=decreasing), ]
if (head)
    out <- head(out, n)

return(out)
}

# shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}

lsos()
 1
Author: ilyas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-29 15:16:24

Staram się, aby ilość obiektów była niewielka podczas pracy w większym projekcie z wieloma etapami pośrednimi. Więc zamiast tworzyć wiele unikalnych obiektów o nazwie

dataframe-> step1 -> step2 -> step3 -> result

raster-> multipliedRast -> meanRastF -> sqrtRast -> resultRast

Pracuję z obiektami tymczasowymi, które nazywam temp.

dataframe -> temp -> temp -> temp -> result

Co pozostawia mi mniej plików pośrednich i więcej przeglądu.

raster  <- raster('file.tif')
temp <- raster * 10
temp <- mean(temp)
resultRast <- sqrt(temp)

To Zapisz więcej pamięci, którą mogę po prostu usunąć temp, gdy nie jest już potrzebna.

rm(temp)

Jeśli potrzebuję kilku plików pośrednich, używam temp1, temp2, temp3.

Do testowania używam test, test2, ...

 -1
Author: mace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-26 10:58:19