R降雪环境问题

Posted

技术标签:

【中文标题】R降雪环境问题【英文标题】:R Snowfall Environments issues 【发布时间】:2015-10-16 14:06:42 【问题描述】:

我正在努力了解 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 函数中声明该函数,错误就会消失。

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

非常感谢!

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

【问题讨论】:

【参考方案1】:

我认为问题不在于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'd 并使用sfExportfoo.bar 导出到每个节点。

【讨论】:

完美,这正是我想要的!此外,如果我需要在另一个脚本中声明但用另一个函数调用的函数中加载(通过 get 函数)或写入(分配)一个变量(......我知道...... :)),我有时会得到找不到环境的错误。我的解决方案是使用 parent.frame() 函数,即。包括 n = 2, 3, 4,具体取决于嵌套函数! snowfall 和 doSnow 有什么区别?

以上是关于R降雪环境问题的主要内容,如果未能解决你的问题,请参考以下文章

在 R 中使用降雪包做一些模拟

R 降雪:并行应用于表格列

使用降雪包并行化 R 代码

如何使用降雪导出预定义函数?

用降雪 R 初始化 MPI 集群

R 中的 sfInit() 降雪包在 Windows 7 上挂起