我正在做一些繁重的计算,我想通过在并行循环中执行它来加快速度。此外,我希望根据当前处理的数据名称将每个计算的结果分配给全局环境:
fun <- function(arg) {
assign(arg, arg, envir = .GlobalEnv)
}
循环
在一个简单的 for 循环中,这将是以下内容,并且效果很好:
for_fun <- function() {
data <- letters[1:10]
for(i in 1:length(data)) {
dat <- quote(data[i])
call <- call("fun", dat)
eval(call)
}
}
# Works as expected
for_fun()
在这个函数中,我首先获取一些数据,对其进行循环,引用它(尽管不是必需的)以在函数调用中使用。实际上,这个函数名称也是动态的,这就是我这样做的原因。
前锋
现在,我想加快速度。我的第一个想法是使用该foreach
软件包(带有doParallel
后端):
foreach_fun <- function() {
# Set up parallel backend
cl <- parallel::makeCluster(parallel::detectCores())
doParallel::registerDoParallel(cl)
data <- letters[1:10]
foreach(i = 1:length(data)) %dopar% {
dat <- quote(data[i])
call <- call("fun", dat)
eval(call)
}
# Stop the parallel backend
parallel::stopCluster(cl)
doParallel::stopImplicitCluster()
}
# Error in { : task 1 failed - "could not find function "fun""
foreach_fun()
将整个quote-call-eval 过程替换为简单地fun(data[i])
解决了错误,但仍然没有分配任何内容。
未来
为了确保包没有问题foreach
,我也尝试了future
包(虽然我不熟悉它)。
future_fun <- function() {
# Plan a parallel future
cl <- parallel::makeCluster(parallel::detectCores())
future::plan(cluster, workers = cl)
data <- letters[1:10]
# Create an explicit future
future(expr = {
for(i in 1:length(data)) {
dat <- quote(data[i])
call <- call("fun", dat)
eval(call)
}
})
# Stop the parallel future
parallel::stopCluster(cl)
future::plan(sequential)
}
# No errors but nothing assigned
# probably the future was never evaluated
future_fun()
强制future
被评估 ( f <- future(...); value(f)
) 触发与使用相同的错误foreach
:Error in { : task 1 failed - "could not find function "fun""
概括
简而言之,我的问题是:
- 如何在并行循环中将变量分配给全局环境?
- 为什么函数查找失败?