1

我正在做一些繁重的计算,我想通过在并行循环中执行它来加快速度。此外,我希望根据当前处理的数据名称将每个计算的结果分配给全局环境:

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)) 触发与使用相同的错误foreachError in { : task 1 failed - "could not find function "fun""

概括

简而言之,我的问题是:

  1. 如何在并行循环中将变量分配给全局环境?
  2. 为什么函数查找失败?
4

0 回答 0