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
并使用 sfExport
将 foo.bar
导出到每个节点。
我正在努力了解 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
并使用 sfExport
将 foo.bar
导出到每个节点。