548 Stimmen

Tricks zur Verwaltung des verfügbaren Speichers in einer R-Sitzung

Welche Tricks verwenden die Leute, um den verfügbaren Speicher einer interaktiven R-Sitzung zu verwalten? Ich verwende die folgenden Funktionen [basierend auf Postings von Petr Pikal und David Hinds in der r-help-Liste im Jahr 2004], um die größten Objekte aufzulisten (und/oder zu sortieren) und um gelegentlich rm() einige von ihnen. Aber die bei weitem effektivste Lösung war ... unter 64-Bit-Linux mit reichlich Speicher zu laufen.

Gibt es noch andere nette Tricks, die Sie uns mitteilen möchten? Einen pro Beitrag, bitte.

# 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)
}

1 Stimmen

Wohlgemerkt, ich zweifle NICHT daran, aber was nützt das schon? Ich bin ziemlich neu bei Speicherproblemen in R, aber ich erlebe einige in letzter Zeit (das ist, warum ich für diesen Beitrag gesucht:) - so bin ich gerade erst anfangen mit all dies. Wie hilft mir das bei meiner täglichen Arbeit?

5 Stimmen

Wenn Sie die Objekte innerhalb einer Funktion sehen wollen, müssen Sie lsos(pos = environment()) verwenden, sonst werden nur globale Variablen angezeigt. Um in den Standardfehler zu schreiben: write.table(lsos(pos=environment()), stderr(), quote=FALSE, sep=' \t ')

0 Stimmen

Warum 64-Bit-Linux und nicht 64-Bit-Windows? Macht die Wahl des Betriebssystems einen nicht-trivialen Unterschied, wenn ich 32 GB Arbeitsspeicher zur Verfügung habe?

3voto

gdkrmr Punkte 622

Wenn Sie an folgenden Themen arbeiten Linux und verwenden möchten mehrere Prozesse und müssen nur noch lesen Operationen an einem oder mehreren Großobjekte verwenden. makeForkCluster anstelle einer makePSOCKcluster . Dies erspart Ihnen auch die Zeit, das große Objekt an die anderen Prozesse zu senden.

2voto

user1265067 Punkte 827

Ich schätze einige der obigen Antworten sehr und folge @hadley und @Dirk, die vorschlagen, R zu schließen und eine source und mit Hilfe der Befehlszeile habe ich eine Lösung gefunden, die bei mir sehr gut funktioniert hat. Ich hatte mit Hunderten von Massenspektren zu tun, von denen jedes etwa 20 MB Speicherplatz beansprucht, also habe ich zwei R-Skripte wie folgt verwendet:

Zunächst eine Verpackung:

#!/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))
   }
}

Mit diesem Skript kontrolliere ich im Grunde, was mein Hauptskript tut runConsensus.r , und ich schreibe die Datenantwort für die Ausgabe. Damit scheint es, dass jedes Mal, wenn der Wrapper das Skript aufruft, R neu geöffnet und der Speicher freigegeben wird.

Ich hoffe, es hilft.

2voto

Ben Punkte 855

Tipp für den Umgang mit Objekten, die umfangreiche Zwischenberechnungen erfordern: Bei der Verwendung von Objekten, deren Erstellung umfangreiche Berechnungen und Zwischenschritte erfordert, finde ich es oft nützlich, einen Teil des Codes mit der Funktion zur Erstellung des Objekts zu schreiben und dann einen separaten Teil des Codes, der mir die Möglichkeit gibt, das Objekt entweder zu erzeugen und als rmd Datei, oder laden Sie sie extern aus einer rmd Datei, die ich bereits zuvor gespeichert habe. Dies ist besonders einfach zu bewerkstelligen in R Markdown unter Verwendung der folgenden Code-Chunk-Struktur.

```{r Create OBJECT}

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

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

LOAD <- TRUE
SAVE <- TRUE
#NOTE: Set LOAD to TRUE if you want to load saved file
#NOTE: Set LOAD to FALSE if you want to generate the object from scratch
#NOTE: Set SAVE to TRUE if you want to save the object externally

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

```

Mit dieser Codestruktur muss ich nur noch folgende Änderungen vornehmen LOAD je nachdem, ob ich das Objekt generieren oder direkt aus einer bereits gespeicherten Datei laden möchte. (Natürlich muss ich es beim ersten Mal erzeugen und speichern, aber danach habe ich die Möglichkeit, es zu laden). Einstellung LOAD <- TRUE umgeht die Verwendung meiner komplizierten Funktion und vermeidet alle darin enthaltenen schweren Berechnungen. Diese Methode erfordert zwar immer noch genügend Speicherplatz, um das betreffende Objekt zu speichern, aber Sie müssen es nicht jedes Mal berechnen, wenn Sie Ihren Code ausführen. Bei Objekten, bei denen viele Zwischenschritte berechnet werden müssen (z. B. bei Berechnungen, die Schleifen über große Arrays beinhalten), kann dies eine beträchtliche Menge an Zeit und Berechnungen einsparen.

1voto

Marcelo Ventura Punkte 511

Laufen

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

von Zeit zu Zeit hilft R auch dabei, ungenutzten, aber noch nicht freigegebenen Speicher freizugeben.

1voto

Matias Thayer Punkte 541

Sie können auch einen gewissen Nutzen daraus ziehen, wenn Sie knitr verwenden und Ihr Skript in Rmd-Chunks unterbringen.

Normalerweise teile ich den Code in verschiedene Teile auf und wähle aus, welcher Teil einen Prüfpunkt im Cache oder in einer RDS-Datei speichert, und

Dort können Sie festlegen, dass ein Chunk im "Cache" gespeichert wird, oder Sie können entscheiden, ob ein bestimmter Chunk ausgeführt werden soll oder nicht. Auf diese Weise können Sie bei einem ersten Durchlauf nur "Teil 1" verarbeiten, bei einer weiteren Ausführung können Sie nur "Teil 2" auswählen, usw.

Beispiel:

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)
```

Als Nebeneffekt könnte Ihnen das auch einige Kopfschmerzen in Bezug auf die Reproduzierbarkeit ersparen :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X