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?

35voto

Shane Punkte 95376

Das ist ein guter Trick.

Ein weiterer Vorschlag ist die Verwendung speichereffizienter Objekte, wo immer dies möglich ist: Verwenden Sie zum Beispiel eine Matrix anstelle eines data.frame.

Hier geht es nicht wirklich um die Speicherverwaltung, aber eine wichtige Funktion, die nicht sehr bekannt ist, ist memory.limit(). Sie können den Standardwert mit diesem Befehl erhöhen: memory.limit(size=2500), wobei die Größe in MB angegeben wird. Wie Dirk bereits erwähnte, müssen Sie 64-Bit verwenden, um die Vorteile dieser Funktion wirklich nutzen zu können.

33voto

Michael Hallquist Punkte 472

Die von Dirk entwickelte verbesserte Objektfunktion gefällt mir sehr gut. In den meisten Fällen reicht mir jedoch eine einfachere Ausgabe mit dem Objektnamen und der Größe aus. Hier ist eine einfachere Funktion mit einer ähnlichen Zielsetzung. Die Speichernutzung kann alphabetisch oder nach Größe geordnet werden, sie kann auf eine bestimmte Anzahl von Objekten beschränkt werden und sie kann auf- oder absteigend geordnet werden. Außerdem arbeite ich oft mit Daten, die mehr als 1 GB groß sind, so dass die Funktion die Einheiten entsprechend ändert.

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

Und hier ist ein Beispiel für die Ausgabe:

> 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

31voto

kpierce8 Punkte 14691

Ich speichere nie einen R-Arbeitsbereich. Ich verwende Importskripte und Datenskripte und gebe alle besonders großen Datenobjekte, die ich nicht oft neu erstellen möchte, in Dateien aus. Auf diese Weise beginne ich immer mit einem frischen Arbeitsbereich und muss keine großen Objekte auslagern. Das ist aber eine sehr schöne Funktion.

30voto

Dennis Jaheruddin Punkte 20439

Leider hatte ich keine Zeit, es ausgiebig zu testen, aber hier ist ein Gedächtnistipp, den ich noch nicht gesehen habe. Bei mir hat sich der benötigte Speicher um mehr als 50% reduziert. Wenn man Daten in R einliest, z.B. mit read.csv, benötigen sie eine gewisse Menge an Speicher. Danach kann man sie mit save("Destinationfile",list=ls()) Das nächste Mal, wenn Sie R öffnen, können Sie load("Destinationfile") Jetzt könnte die Speichernutzung zurückgegangen sein. Es wäre schön, wenn jemand bestätigen könnte, ob dies zu ähnlichen Ergebnissen mit einem anderen Datensatz führt.

28voto

Dirk Eddelbuettel Punkte 345316

Zur weiteren Veranschaulichung der gemeinsamen Strategie der häufigen Neustarts können wir Folgendes verwenden Kleinere die es uns ermöglicht, einfache Ausdrücke direkt über die Befehlszeile auszuführen. Hier ist ein Beispiel, das ich manchmal verwende, um verschiedene BLAS für einen einfachen Crossprod.

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

Gleichermaßen,

 r -lMatrix -e'example(spMatrix)'

lädt das Matrix-Paket (über den Schalter --packages | -l) und führt die Beispiele für die Funktion spMatrix aus. Da r immer "frisch" startet, ist diese Methode auch ein guter Test während der Paketentwicklung.

Nicht zuletzt eignet sich r auch hervorragend für den automatisierten Batch-Modus in Skripten, die den Shebang-Header '#!/usr/bin/r' verwenden. Rscript ist eine Alternative, wenn Littler nicht verfügbar ist (z.B. unter Windows).

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