R降雪环境问题

时间:2015-07-26 09:02:43

标签: r parallel-processing snowfall

我试图了解Snowfall图书馆及其用法。

编写了一个利用环境的模拟后,我遇到了以下问题。如果我在并行模式下使用文件来加载函数,那么该函数似乎使用的是与在并行模式direclty中声明函数时不同的环境。

为了使事情更清楚,让我们考虑以下两个脚本:

q_func.R 声明函数

foo.bar <- function(x, envname) assign("val", x, envir = get(envname))
# assigns the value x to the variable "val" in the environment envname

q_snowfall.R 使用降雪的主要功能

library(snowfall)
SnowFunc <- function(envname) {
    # load the functions

    # Option 1 not working
    source("q_func.R")
    # Option 2 working...
    # foo.bar <- function(x, envname) assign("val", x, envir = get(envname))


    # create the new environment
    assign(envname, new.env())

    # use the function as declared in q_func.R 
    # to assign random numbers to the new env
    foo.bar(x = rnorm(1), envname = envname)

    # return the environment including the random values
    return(get("val", envir = get(envname)))
}

sfInit(parallel = TRUE, cpus = 2)
# create environment 'a' and 'b' that each will get a new variable 
# called 'val' that gets assigned a random value

envs <- c("a", "b")
result <- sfClusterApplyLB(envs, SnowFunc)
sfStop()

如果我执行脚本“q_snowfall.R”,我会收到错误

Error in checkForRemoteErrors(val) : 
  2 nodes produced errors; first error: object 'a' not found

但是,如果我使用第二个选项(在SnowFunc函数中声明函数,则错误消失。

你知道Snowfall如何处理不同的环境吗?或者你甚至有一个问题的解决方案。 (注意'q_func.R'实际上需要大约100行代码,因此我更愿意将它放在一个单独的文件中,因此“保留选项2”不是解决方案!)

非常感谢!

修改 如果我将所有get(envname)更改为get(envname, envir = globalenv()),它似乎有效。但在我看来,这或多或少是一种解决方法,而不是一种非常降雪的解决方案。

1 个答案:

答案 0 :(得分:1)

我认为问题不在于snowfall,而在于您通过名称(作为字符)传递环境的事实。您不需要更改get的所有内容,并且查看globalEnv可能确实不安全。

只需更改get中的foo.bar电话就可以查看parent.frame()(即foo.bar被调用的环境)。以下工作在我的机器上。

q_func.R

foo.bar <- function(x, envname) assign("val", x, envir=get(envname,
                                pos=parent.frame()))

(不是这样)新 q_snowfall.R

library(snowfall)
SnowFunc <- function(envname) {

    assign(envname, new.env())
    foo.bar(x = rnorm(1), envname = envname)

    return(get("val", envir = get(envname)))
}

source("q_func.R")
sfInit(parallel = TRUE, cpus = 2)
sfExport("foo.bar")

envs <- c("a", "b")
result <- sfClusterApplyLB(envs, SnowFunc)
sfStop()

另请注意,我source在启动群集之前,使用sfExportfoo.bar导出到每个节点。