在 foreach 循环中找不到变量或环境的函数
Functions not finding variables, or environment, when inside a foreach loop
我正在尝试构建一个 R package
,其中包含几个 nested foreach
循环中的顶级函数。这个顶级函数然后调用一组进一步的嵌套函数。我遇到的问题是词法范围,较低级别的函数找不到我放置变量的环境或变量。我已尝试使用 attach
,根据此示例 attach but lower functions can still no not see necessary arguments. I know there is something specific about doMPI using a forking method. This is on Ubuntu Linux (16.04), using doMPI (0.2.2) and foreach (1.4.3) and openmpi. This is a mwe of a much bigger model that I have. The package, and a script to run/test it called toymod4 package 可供下载。
#' Test function level 1
#' @param num.sim first variable for function 1
#' @param num.per second variable for function 1
#' @param num.day third variable for function 1
#' @param fun2.params parameters for function 2
#' @param fun31.params parameters for first call of function 3
#' @param fun32.params parameters for second call of funtion 3
#' @param fun4.params parameters for call to function 4
#' @export fun1
fun1 <- function (fun2.params, fun31.params, fun32.params, fun4.params,
num.sim=10, num.per=8, num.day=5, ...) {
final.results <- data.frame (foreach::`%dopar%`(
foreach::`%:%`(foreach::foreach(j = 1:num.sim,
.combine = cbind,
.packages= c("toymod4")),
foreach::foreach (i = 1:num.per,
.packages = c("toymod4"),
.combine=rbind)), {
e1 <- new.env()
e1 <- list2env(c(fun2.params, fun31.params, fun32.params,
fun4.params), e1)
out3 <- replicate(num.day, fun2(e1, var21, var22, fun22on))
out2 <- data.frame(mean(out3))
}
)
)
## save outputs for subsequent analyses if required
saveRDS(final.results, file = paste(num.day ,"_", num.per, "_", num.sim, "_",
format(Sys.time(), "%d_%m_%Y"),
".rds", sep=""))
return(final.results)
}
#' Test function level 2
#' @param var21 first variable for function 2
#' @param var22 second variable for function 2
#' @param fun22on turn this copy of fun3 on or off
#' @param env environment to get variables from
#' @export fun2
fun2 <- function (env, var21, var22, fun22on, ...) {
attach(env)
out21 <- ifelse (rpois(1, var21) > 0, var22 * fun3(e1, fun3on, var31), 0)
out22 <- ifelse (fun22on, fun3(e1, fun3on, var31), 0)
out2 <- out21 + out22
detach(env)
out2
}
#' Test function level 3
#' @param var31 first variable for function 3
#' @param fun3on turn the formula on or off
#' @export fun3
fun3 <- function (env, fun3on, var31, ...) {
attach(env)
out31 <- ifelse (fun3on, var31, 1)
out32 <- ifelse (fun3on, fun4(e1, fun4on, var41), 0)
out3 <- out31 + out32
detach(env)
out3
}
#' Test function level 4
#' @param var41 first variable for function 4
#' @param fun4on turn the formula on or off
#' @export fun4
fun4 <- function (env, fun4on, var41, ...) {
attach(env)
out4 <- ifelse (fun4on, var41, 1)
detach(env)
out4
}
在 Steve Weston 的慷慨帮助下,我已经设法解决了这个问题。我没有尝试解释所有内容,而是将其发布在 github 上的这个地址
https://github.com/jamaas/VarPasMpiExamp.git
这是将变量值传递给包含在 foreach 循环中的函数的一种方法。从理论上讲,它应该适用于 R,foreach 在任何操作系统上,使用任何并行后端,但尚未在所有系统上进行测试。此版本的开发和测试是在 Ubuntu 16.04 (Debian) Linux 上完成的。让我知道此方法是否适合您,或者特别是如果您有更简单、更优雅的解决方案。
我正在尝试构建一个 R package
,其中包含几个 nested foreach
循环中的顶级函数。这个顶级函数然后调用一组进一步的嵌套函数。我遇到的问题是词法范围,较低级别的函数找不到我放置变量的环境或变量。我已尝试使用 attach
,根据此示例 attach but lower functions can still no not see necessary arguments. I know there is something specific about doMPI using a forking method. This is on Ubuntu Linux (16.04), using doMPI (0.2.2) and foreach (1.4.3) and openmpi. This is a mwe of a much bigger model that I have. The package, and a script to run/test it called toymod4 package 可供下载。
#' Test function level 1
#' @param num.sim first variable for function 1
#' @param num.per second variable for function 1
#' @param num.day third variable for function 1
#' @param fun2.params parameters for function 2
#' @param fun31.params parameters for first call of function 3
#' @param fun32.params parameters for second call of funtion 3
#' @param fun4.params parameters for call to function 4
#' @export fun1
fun1 <- function (fun2.params, fun31.params, fun32.params, fun4.params,
num.sim=10, num.per=8, num.day=5, ...) {
final.results <- data.frame (foreach::`%dopar%`(
foreach::`%:%`(foreach::foreach(j = 1:num.sim,
.combine = cbind,
.packages= c("toymod4")),
foreach::foreach (i = 1:num.per,
.packages = c("toymod4"),
.combine=rbind)), {
e1 <- new.env()
e1 <- list2env(c(fun2.params, fun31.params, fun32.params,
fun4.params), e1)
out3 <- replicate(num.day, fun2(e1, var21, var22, fun22on))
out2 <- data.frame(mean(out3))
}
)
)
## save outputs for subsequent analyses if required
saveRDS(final.results, file = paste(num.day ,"_", num.per, "_", num.sim, "_",
format(Sys.time(), "%d_%m_%Y"),
".rds", sep=""))
return(final.results)
}
#' Test function level 2
#' @param var21 first variable for function 2
#' @param var22 second variable for function 2
#' @param fun22on turn this copy of fun3 on or off
#' @param env environment to get variables from
#' @export fun2
fun2 <- function (env, var21, var22, fun22on, ...) {
attach(env)
out21 <- ifelse (rpois(1, var21) > 0, var22 * fun3(e1, fun3on, var31), 0)
out22 <- ifelse (fun22on, fun3(e1, fun3on, var31), 0)
out2 <- out21 + out22
detach(env)
out2
}
#' Test function level 3
#' @param var31 first variable for function 3
#' @param fun3on turn the formula on or off
#' @export fun3
fun3 <- function (env, fun3on, var31, ...) {
attach(env)
out31 <- ifelse (fun3on, var31, 1)
out32 <- ifelse (fun3on, fun4(e1, fun4on, var41), 0)
out3 <- out31 + out32
detach(env)
out3
}
#' Test function level 4
#' @param var41 first variable for function 4
#' @param fun4on turn the formula on or off
#' @export fun4
fun4 <- function (env, fun4on, var41, ...) {
attach(env)
out4 <- ifelse (fun4on, var41, 1)
detach(env)
out4
}
在 Steve Weston 的慷慨帮助下,我已经设法解决了这个问题。我没有尝试解释所有内容,而是将其发布在 github 上的这个地址 https://github.com/jamaas/VarPasMpiExamp.git 这是将变量值传递给包含在 foreach 循环中的函数的一种方法。从理论上讲,它应该适用于 R,foreach 在任何操作系统上,使用任何并行后端,但尚未在所有系统上进行测试。此版本的开发和测试是在 Ubuntu 16.04 (Debian) Linux 上完成的。让我知道此方法是否适合您,或者特别是如果您有更简单、更优雅的解决方案。