如何在并行代码中使用从box模块导入的名称?
解决box::use加载函数在foreach并行中找不到的问题
问题复现
mod.r:
#' @export run_sqrt <- function (x) { sqrt(x) }
mwe.r
box::use( ./mod[...], parallel, dp = doParallel, foreach[foreach, `%dopar%`], ) cl <- parallel$makeCluster(2L) dp$registerDoParallel(cl) foreach(i = 1 : 5) %dopar% { run_sqrt(i) } parallel$stopCluster(cl)
运行报错:
Error in { : task 1 failed - "could not find function "run_sqrt""
尝试parallel::clusterExport(cluster, setdiff(ls(), "cluster"))无效,原因是box::use加载的函数不在全局环境的变量列表中,默认不会被导出到并行节点。
解决方案
方案1:在并行任务中重新加载模块
每个并行子进程是独立的运行环境,直接在任务代码块内加载所需模块即可:
foreach(i = 1 : 5) %dopar% { box::use(./mod[run_sqrt]) run_sqrt(i) }
方案2:显式导出模块中的函数到集群节点
先从模块中取出函数对象,再导出到所有并行节点:
cl <- parallel$makeCluster(2L) dp$registerDoParallel(cl) # 从模块中获取函数并赋值到全局环境 run_sqrt_fun <- mod$run_sqrt # 导出函数到集群节点 parallel::clusterExport(cl, "run_sqrt_fun") foreach(i = 1 : 5) %dopar% { run_sqrt_fun(i) } parallel$stopCluster(cl)
方案3:使用foreach的.export参数
显式指定需要同步到子节点的函数名,前提是函数已在全局环境中:
cl <- parallel$makeCluster(2L) dp$registerDoParallel(cl) # 将模块函数赋值到全局环境 run_sqrt <- mod$run_sqrt foreach(i = 1 : 5, .export = "run_sqrt") %dopar% { run_sqrt(i) } parallel$stopCluster(cl)
内容的提问来源于stack exchange,提问作者Ferroao
相关产品推荐
相关产品推荐

