Ich benutze GNU R auf einem Ubuntu-Lucid-PC mit 4 CPUs. Um alle 4 CPUs nutzen zu können, habe ich das Paket "r-cran-multicore" installiert. Da das Handbuch des Pakets keine praktischen Beispiele enthält, die ich verstehe, benötige ich Ratschläge zur Optimierung meines Skripts, um alle 4 CPUs nutzen zu können.
Mein Datensatz ist ein data.frame (P1 genannt) mit 50.000 Zeilen und 1600 Spalten. Ich möchte für jede Zeile das Maximum, die Summe und den Mittelwert berechnen. Mein Skript sieht folgendermaßen aus:
p1max <- 0
p1mean <- 0
p1sum <-0
plength <- length(P1[,1])
for(i in 1:plength){
p1max <- c(p1max, max(P1[i,]))
p1mean <- c(p1mean, mean(P1[i,]))
p1sum <- c(p1sum, sum(P1[i,]))
}
Kann mir jemand sagen, wie ich das Skript ändern und ausführen soll, um alle 4 CPUs zu nutzen?
Antworten:
Verwenden Sie foreach und doMC . Die ausführliche Erklärung finden Sie hier . Ihr Skript wird die Zeile sehr wenig verändern
sollte geändert werden in
Die Voraussetzungen für ein Multitasking-Skript, das diese Pakete verwendet, sind:
Hinweis zur Vorsicht. Laut Dokumentation können Sie dies nicht in der GUI verwenden.
Benötigen Sie für Ihr Problem wirklich Multitasking? Ihr data.frame benötigt ungefähr 1,2 GB RAM, sodass er in Ihren Arbeitsspeicher passt. So können Sie einfach anwenden:
Das Ergebnis ist eine Matrix mit Zusammenfassungen jeder Zeile.
Sie können auch die Funktion mclapply verwenden, die im Paket multicore enthalten ist. Dann könnte Ihr Skript so aussehen:
Dies gibt die Liste zurück, wobei das i-te Element die Zusammenfassung der i-ten Zeile ist. Sie können es mit sapply in eine Matrix konvertieren
quelle
Sie haben bereits eine Antwort darauf, wie Sie mehr als einen Kern verwenden können, aber das eigentliche Problem liegt in der Art und Weise, wie Sie Ihre Schleifen geschrieben haben. Erweitern Sie niemals Ihren Ergebnisvektor / Objekt bei jeder Iteration einer Schleife . Wenn Sie dies tun, zwingen Sie R, Ihren Ergebnisvektor / Ihr Ergebnisobjekt zu kopieren und zu erweitern, was alles Zeit kostet. Weisen Sie stattdessen genügend Speicherplatz vorab zu, bevor Sie die Schleife starten, und füllen Sie diese bei Bedarf aus. Hier ist ein Beispiel:
Oder Sie können diese Dinge tun über
apply()
:Beachten Sie jedoch, dass dies nicht schneller ist, als die Schleife ordnungsgemäß und manchmal langsamer auszuführen.
Achten Sie jedoch immer auf vektorisierten Code. Sie können Zeilensummen und Mittelwerte mit
rowSums()
undrowMeans()
erstellen, die schneller als die Schleife oder dieapply
Versionen sind:Wenn ich ein Wettmann wäre, hätte ich Geld für den dritten Ansatz, den ich beim Schlagen erwähne,
foreach()
oder für die anderen Optionen mit mehreren Kernen in einem Geschwindigkeitstest für Ihre Matrix, weil sie die Dinge erheblich beschleunigen müssten, um den Mehraufwand beim Einrichten der zu rechtfertigen separate Prozesse, die auf die verschiedenen CPU-Kerne verteilt werden.Update: Nach dem Kommentar von @shabbychef ist es schneller, die Summen einmal zu machen und bei der Berechnung des Mittelwerts wiederzuverwenden?
Nicht in diesem Testlauf, aber das ist alles andere als erschöpfend ...
quelle
rowSums
zu verwenden, um das Zeilenmittel zu berechnen (es sei denn, mir fehlt etwas in Bezug auf z. B. Na oder NaN). Der Code in Ihrem dritten Ansatz summiert jede Spalte zweimal .rowSums
undrowMeans
sind sehr kompilierten Code optimiert und was gewinnen wir in nur einmal die Summen der Berechnung, verlieren wir wieder in die mittlere Berechnung in interpretierten Code zu tun.system.time({ for (iii in c(1:1000)) { p1max3 <- apply(p1, 1, max) p1mean3 <- rowMeans(p1) p1sum3 <- rowSums(p1) } })
und auf ähnliche Weisesystem.time({ for (iii in c(1:1000)) { p1max4 <- apply(p1, 1, max) p1sum4 <- rowSums(p1) p1mean4 <- p1sum4 / ncol(p1) } })
; Die Version, die die Summe nicht neu berechnet, benötigt auf meinem Computer 1,368 Sekunden. der, der das tut, braucht 1.396. wiederrowMeans
undrowSums
in effiziente, optimierte kompilierten Code implementiert werden , sie gehen nur schwer zu schlagen sein.rowMean
diese mit einem Allzweck-R-Tool schwer zu übertreffen sein wird*apply
. Sie scheinen jedoch anzunehmen, dass es schneller ist, 10000 Zahlen zweimal überrowMean
undrowSum
nicht nur einmal zu summieren und den in R eingebauten Divisionsoperator zu verwenden. Ich weiß, dass R einige Effizienzprobleme hat ( z. B. die jüngste Entdeckung des Problems der geschweiften Klammern gegenüber der Klammer), aber das scheint verrückt zu sein.Schauen Sie sich die Schnee- und Schneefallpakete an. Viele Beispiele mit denen ...
Wenn Sie diesen bestimmten Code beschleunigen möchten, anstatt R und Parallelität zu lernen, sollten Sie dies tun
quelle