r-如何初始化工作程序以并行使用包函数



我正在开发一个R包,并试图在其中使用并行处理来解决一个令人尴尬的并行问题。我想写一个循环或函数,使用我的包中的其他函数。我在Windows中工作,我尝试过使用parallel::parLapplyforeach::%dopar%,但无法让worker(core(访问我的包中的功能。下面是一个包含两个函数的简单包的示例,其中第二个函数在并行循环中使用%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()加载包并调用slowadd函数时,返回Error in { : task 1 failed - "could not find function "add10""

我还尝试过用我的包显式初始化工人:

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

但是我得到了错误CCD_ 7。

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

由于人们的帮助,我能够用包的函数初始化worker。通过确保在NAMESPACE中导出所有需要的包函数,并使用devtools::install()安装我的包,foreach能够找到要初始化的包。示例的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)
} 

这是有效的,但不是一个理想的解决方案。首先,这会导致工作流程变慢。每次我对包进行更改并想测试它(在合并并行性之前(时,我都使用devtools::load_all(),但现在每次我都必须重新安装包,当包很大时,这会很慢。其次,并行循环中需要的每个函数都需要导出,以便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)
}

最新更新