在几分钟内并行化R中的代码

如果您相信构造型,那么R语言是一种专门用于统计和机器学习的语言。第二个构造型是纯R代码不是很快:首先是因为它被解释了,其次是因为它是顺序执行的。当然,刻板印象与现实有某种联系,否则它们将不存在,这就是为什么它们是刻板印象,它给出了一个世界的极其简化的图景,其中丢失了许多细节。特别是,今天,我想分享一种令人惊讶的简单方法,即向R添加并行性并乘以加快现有代码的执行速度,而无需对其进行任何重大更改。所有这些仅需几分钟即可完成。



假设我们有一个包含许多行和列的矩阵或数据表,并且我们想对每一行执行某种相同类型的计算。例如,计算其值的平方和。将计算移入一个函数并为每一行调用它是合乎逻辑的。



初始数据:



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


功能:



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


您可以简单地在线路上循环并将此功能应用于每条线路,但这不是R的最佳推荐方式。每条线路的计算将顺序执行,所有计算将在同一内核上执行。这种代码实际上不是很有效。为了以防万一,让我们写下这个选项并测量执行时间:



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


我们测量执行时间:



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


我们得到:



 :  4.474074 secs


我们将以此时间作为与其他方法进行比较的起点。



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



好,仅此而已。该方法非常简单。对我来说,当我发现他的时候,那简直是天赐之物。当前R不支持并行计算是真的吗?取决于对这个问题的观点,取决于其陈述的严重性。但是从某种意义上讲,我们可以假设它确实支持。




All Articles