R降雪环境问题

R Snowfall Environments issues

我正在努力了解 Snowfall 库及其用法。

在编写使用环境的模拟后,我遇到了以下问题。如果我获取一个文件以在并行模式下加载函数,该函数似乎使用了与我在并行模式直接声明函数时不同的环境。

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

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 函数中声明函数,错误就会消失。

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

非常感谢!

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

我认为问题不在于 snowfall,而在于您按名称(作为角色)传递环境。您不需要更改 get 的所有出现,并且在 globalEnv 中查看它可能确实不安全。

foo.bar 中的 get 调用更改为在 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 导出到每个节点。