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?

23voto

Ben B-L Punkte 426

Sowohl aus Geschwindigkeits- als auch aus Speichergründen werde ich bei der Erstellung eines großen Datenrahmens über eine komplexe Reihe von Schritten diesen (den gerade erstellten Datensatz) in regelmäßigen Abständen auf die Festplatte flushen, an alles anhängen, was vorher war, und ihn dann neu starten. Auf diese Weise arbeiten die Zwischenschritte nur an kleinen Datenrahmen (was gut ist, da z.B., rbind verlangsamt sich bei größeren Objekten erheblich). Der gesamte Datensatz kann am Ende des Prozesses wieder eingelesen werden, wenn alle Zwischenobjekte entfernt wurden.

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 )

17voto

geotheory Punkte 21109

Ich möchte nur darauf hinweisen, dass data.table des Pakets tables() scheint ein ziemlich guter Ersatz für Dirks .ls.objects() benutzerdefinierte Funktion (detailliert in früheren Antworten), allerdings nur für data.frames/tables und nicht z.B. für Matrizen, Arrays, Listen.

16voto

  1. Ich bin in der glücklichen Lage, dass meine großen Datensätze vom Gerät in "Chunks" (Teilmengen) von etwa 100 MB (32-Bit-Binärformat) gespeichert werden. So kann ich die Vorverarbeitungsschritte (Löschen uninformativer Teile, Downsampling) nacheinander durchführen, bevor ich den Datensatz zusammenführe.

  2. Aufruf von gc () "von Hand" kann helfen, wenn die Größe der Daten an den verfügbaren Speicher heranreicht.

  3. Manchmal benötigt ein anderer Algorithmus viel weniger Speicherplatz.
    Manchmal gibt es einen Kompromiss zwischen Vektorisierung und Speicherverbrauch.
    vergleichen: split & lapply vs. a for Schleife.

  4. Um eine schnelle und einfache Datenanalyse zu ermöglichen, arbeite ich häufig zunächst mit einer kleinen zufälligen Teilmenge ( sample () ) der Daten. Sobald das Datenanalyseskript/.Rnw fertig ist, gehen der Datenanalysecode und die kompletten Daten an den Berechnungsserver zur Berechnung über Nacht / über das Wochenende / ....

11voto

Georg Schnabel Punkte 621

Die Verwendung von Umgebungen anstelle von Listen, um Sammlungen von Objekten zu handhaben, die einen erheblichen Teil des Arbeitsspeichers beanspruchen.

Der Grund: Jedes Mal, wenn ein Element einer list Struktur geändert wird, wird die gesamte Liste vorübergehend dupliziert. Dies wird zum Problem, wenn der Speicherbedarf der Liste etwa die Hälfte des verfügbaren Arbeitsspeichers beträgt, da dann Daten auf die langsame Festplatte ausgelagert werden müssen. Umgebungen hingegen unterliegen diesem Verhalten nicht und können ähnlich wie Listen behandelt werden.

Hier ist ein Beispiel:

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

In Verbindung mit Strukturen wie big.matrix o data.table die es erlauben, ihren Inhalt an Ort und Stelle zu ändern, kann eine sehr effiziente Speichernutzung erreicht werden.

8voto

user1436187 Punkte 3156

El ll Funktion in gData Paket kann auch den Speicherverbrauch der einzelnen Objekte anzeigen.

gdata::ll(unit='MB')

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