我试图了解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())
,它似乎有效。但在我看来,这或多或少是一种解决方法,而不是一种非常降雪的解决方案。
答案 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
在启动群集之前,使用sfExport
将foo.bar
导出到每个节点。