R-用DOMC替换并行Plyr



考虑数据上的标准分组操作:

library(plyr)
library(doMC)
library(MASS) # for example
nc <- 12
registerDoMC(nc)
d <- data.frame(x = c("data", "more data"), g = c("group1", "group2"))
y <- "some global object"
res <- ddply(d, .(g), function(d_group) {
   # slow, complicated operations on d_group
}, .parallel = FALSE)

通过简单地编写.parallel = TRUE来利用多核设置是微不足道的。这是我最喜欢的Plyr的功能之一

但是,随着plyr被弃用(我认为),并且基本上被dplyr,purrr等取代,平行处理的解决方案已变得更加详尽:

library(dplyr)
library(multidplyr)
library(parallel)
library(MASS) # for example
nc <- 12
d <- tibble(x = c("data", "more data"), g = c("group1", "group2"))
y <- "some global object"
cl <- create_cluster(nc)
set_default_cluster(cl)
cluster_library(cl, packages = c("MASS"))
cluster_copy(cl, obj = y)
d_parts <- d %>% partition(g, cluster = cl)
res <- d_parts %>% collect() %>% ungroup()
rm(d_parts)
rm(cl)

您可以想象,此示例可以考虑到循环中需要的每个软件包和对象需要多长时间,需要自己的cluster_*命令将其复制到节点上。非平行的plyr-to-dplyr翻译只是一个简单的dplyr::group_by结构,不幸的是,没有简短的方法可以启用并行处理。所以,我的问题是:

  • 这实际上是将我的代码从plyr转换为dplyr的首选方法吗?
  • Plyr的幕后发生了什么样的魔术,使打开并行处理变得如此容易?是否有一个原因,这种功能特别困难地添加到dplyr,这就是为什么它还不存在?
  • 我的两个示例在执行代码方面根本不同吗?
  1. 我认为没有一种真正的"优先"方法将{plyr}代码转换为{dplyr}。

  2. 在评论中 @aurèle做得比我在描述{plyr}和{domc}之间的连接方面做得比以往任何时候都做得更好。发生的一件事是激励措施有所改变。{DOMC}来自Revolution Analytics(自Microsoft购买以来)。但是开发Dplyr的Hadley目前在Rstudio工作。这两家公司在IDE领域竞争。因此,也许他们的包装并不能使他们的包装既可以很好地一起玩。我看到的唯一平行性形式是{sprapllyr},它们使它们相对"容易"。但是,我真的不建议使用Spark Futinging futing futing for Spark进行单台机器的并行处理。

  3. @aurèle再次在解释执行差异方面做得很好。您的新代码使用psock群集和旧的代码叉。叉子在写模式下使用副本来访问RAM,因此并行进程可以立即访问相同数据的访问。psock簇就像产卵的新副本 - 他们必须加载库并收到数据的明确副本。

您可以使用类似于...

的模式
library(dplyr)
library(purrr)
library(future)
plan(multicore)
options(mc.cores = availableCores())
d <- data.frame(x = 1:8, g = c("group1", "group2", "group3", "group4"))
y <- "some global object"

split(d, d$g) %>% 
  map(~ future({Sys.sleep(5);mean(.x$x)})) %>% 
  map_df(~value(.x))

...在map_df步骤上有一些精巧的操作,以进行一些并行处理。请注意,在{purrr}下,〜是匿名函数语法,其中.x是已映射的值。

如果您想危险地生活,则可以通过在{purrr}

中使用私人方法来创建类似事物的版本
mcmap <- function(.x, .f, ...) {
  .f <- as_mapper(.f, ...)
  mclapply(.x, function(.x) {
    force(.f)
    .Call(purrr:::map_impl, environment(), ".x", ".f", "list")
  }) %>%
    map(~ .x[[1]])
}

相关内容

  • 没有找到相关文章

最新更新