Parallelisierung des Codes in R in wenigen Minuten

Wenn Sie den Stereotypen glauben, dann ist die R-Sprache etwas hochspezialisiertes für Statistik und maschinelles Lernen. Das zweite Stereotyp ist, dass reiner R-Code nicht sehr schnell ist: erstens, weil er interpretiert wird, und zweitens, weil er sequentiell ausgeführt wird. Natürlich haben Stereotypen einen gewissen Bezug zur Realität, sonst würden sie nicht existieren, aber deshalb sind sie Stereotypen, die ein extrem vereinfachtes Bild der Welt vermitteln, in der viele Details verloren gehen. Insbesondere möchte ich heute eine überraschend einfache Möglichkeit vorstellen, R Parallelität hinzuzufügen und die Ausführung des vorhandenen Codes um ein Vielfaches zu beschleunigen, ohne größere Änderungen daran vornehmen zu müssen. All dies ist in nur wenigen Minuten erledigt.



Angenommen, wir haben eine Matrix oder Datentabelle, die eine Reihe von Zeilen und Spalten enthält, und wir möchten für jede der Zeilen dieselbe Art von Berechnung durchführen. Berechnen Sie beispielsweise die Summe der Quadrate seiner Werte. Es ist logisch, die Berechnungen in eine Funktion zu verschieben und für jede Zeile aufzurufen.



Ausgangsdaten:



a <- matrix(rnorm(500000, mean=0, sd=2), 100000, 50)


Funktion:



sum.of.squares <- function(n) {
  n_sq <- sapply(n, function(x) x^2)
  sum(n_sq)
}


Sie können einfach die Linien durchlaufen und diese Funktion auf jede der Linien anwenden. Dies ist jedoch nicht die am meisten empfohlene Methode für R. Die Berechnungen für jede der Linien werden nacheinander durchgeführt. Alle Berechnungen werden auf demselben Kern durchgeführt. Diese Art von Code ist wirklich nicht sehr effizient. Für alle Fälle schreiben wir diese Option auf und messen die Ausführungszeit:



b <- vector()
for(i in 1:dim(a)[1]) {
  b[i] <- sum.of.squares(a[i,])
}


Wir messen die Ausführungszeit:



b <- vector()
start_time <- Sys.time()
for(i in 1:dim(a)[1]) {
  b[i] <- sum.of.squares(a[i,])
}
timediff <- difftime(Sys.time(), start_time)
cat(" : ", timediff, units(timediff))


Wir bekommen:



 :  4.474074 secs


Wir werden diese Zeit als Ausgangspunkt für den Vergleich mit anderen Methoden verwenden.



. R apply(). , : 1, 2. , . – sapply(), . – . , apply() :



b <- apply(a, 1, function(x) sum.of.squares(x))


, . , , :



start_time <- Sys.time()
b <- apply(a, 1, function(x) sum.of.squares(x))
timediff <- difftime(Sys.time(),start_time)
cat(" : ", timediff, units(timediff))


:



 : 4.484046 secs


, . : , .



, , R , . : apply(), , . , , . , apply(). apply() by(), eapply(), lapply(), Map(), .mapply(), mapply(), replicate(), sapply(), tapply(), vapply(). , future_apply:



install.packages("future.apply") 


– . , :



library("future.apply")
plan(multiprocess)


. , . future::plan(). , , apply "future_". :



b <- future_apply(a, 1, function(x) sum.of.squares(x))


:



start_time <- Sys.time()
b <- future_apply(a, 1, function(x) sum.of.squares(x))
timediff <- difftime(Sys.time(),start_time)
cat(" : ", timediff, units(timediff))


:



 :  1.283569 secs


Intel Core i7-8750H 12 . 12-, .



. , , , , , . , , future_sapply, . . – . , , , (a <- data.frame(a)), , 8 . .



Nun, das ist alles. Die Methode ist recht einfach. Als ich von ihm erfuhr, war es für mich nur ein Glücksfall. Stimmt es, dass das aktuelle R Parallel Computing nicht unterstützt? Hängt vom Standpunkt zu diesem Thema und von der Schwere seiner Aussage ab. Aber in gewissem Sinne können wir davon ausgehen, dass es unterstützt.




All Articles