繁体   English   中英

如何初始化worker并行使用package个函数

[英]How to initialize workers to use package functions in parallel

我正在开发一个 R package 并尝试在其中使用并行处理来解决一个令人尴尬的并行问题。 我想编写一个循环或函数,使用我的 package 中的其他函数。我在 Windows 工作,我尝试使用parallel::parLapplyforeach::%dopar% ,但无法让工作人员(核心)到访问我的 package 中的函数。这是一个带有两个函数的简单 package 的示例,其中第二个使用%dopar%在并行循环中调用第一个:

add10 <- function(x) x + 10

slowadd <- function(m) {
  cl <- parallel::makeCluster(parallel::detectCores() - 1)
  doParallel::registerDoParallel(cl)

  `%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached

  foreach::foreach(i = 1:m) %dopar% {
    Sys.sleep(1)
    add10(i)
  }

  stopCluster(cl)
}

当我使用devtools::load_all()加载 package 并调用slowadd function 时, Error in {: task 1 failed - "could not find function "add10""被返回。

我还尝试使用我的 package 显式初始化工作人员:

add10 <- function(x) x + 10

slowadd <- function(m) {
  cl <- parallel::makeCluster(parallel::detectCores() - 1)
  doParallel::registerDoParallel(cl)

  `%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached

  foreach::foreach(i = 1:m, .packages = 'mypackage') %dopar% {
    Sys.sleep(1)
    add10(i)
  }

  stopCluster(cl)
}

但我收到错误Error in e$fun(obj, substitute(ex), parent.frame(), e$data): worker initialization failed: there is no package called 'mypackage'

如何让工作人员访问我的 package 中的功能? 使用foreach的解决方案会很棒,但我对使用parLapply或其他函数/包的解决方案完全开放。

感谢人们的有用评论,我能够用我的包的功能初始化工作人员。 通过确保所需的所有 package 函数都在 NAMESPACE 中导出并使用devtools::install()安装我的 package, foreach能够找到 package 进行初始化。 该示例的 R 脚本如下所示:

#' @export
add10 <- function(x) x + 10

#' @export
slowadd <- function(m) {
  cl <- parallel::makeCluster(parallel::detectCores() - 1)
  doParallel::registerDoParallel(cl)

  `%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached

  out <- foreach::foreach(i = 1:m, .packages = 'mypackage') %dopar% {
    Sys.sleep(1)
    add10(i)
  }

  stopCluster(cl)
  return(out)
} 

这是有效的,但它不是一个理想的解决方案。 首先,它使工作流程慢得多。 每次我对 package 进行更改并想测试它(在合并并行性之前)时,我都在使用devtools::load_all() ),但现在我每次都必须重新安装 package,当 package 很大时,这很慢。 其次,需要导出并行循环中需要的每个 function,以便foreach可以找到它。 我的实际用例有很多我宁愿保留在内部的小实用程序功能。

您可以在 foreach 循环内使用devtools::load_all()或使用source加载您需要的函数。

out <- foreach::foreach(i = 1:m ) %dopar% {
    Sys.sleep(1)
    source("R/some_functions.R")
    load("R/sysdata.rda")
    add10(i)
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM