2017-09-19 2 views
0

nested foreach 루프 내에서 최상위 함수를 포함하는 R package을 작성하려고합니다. 그런 다음이 최상위 함수는 일련의 추가 중첩 함수를 호출합니다. 내가 가진 문제는 렉시 컬 스코핑 (lexical scoping)이다. 하위 레벨 함수는 변수 나 변수를 넣을 환경을 찾을 수 없다. 이 예제에 따라 attach과 같이 attach을 사용하려고 시도했지만 더 낮은 함수는 여전히 필요한 인수를 볼 수 없습니다. 나는 거기에 포크 방법을 사용하여 doMPI에 대해 특정한 것이 있음을 압니다. 이것은 doMPI (0.2.2)와 foreach (1.4.3) 및 openmpi를 사용하여 Ubuntu Linux (16.04)에 있습니다. 이것은 내가 가지고있는 훨씬 더 큰 모델의 mwe입니다. 패키지 및 실행/테스트 할 스크립트는 toymod4 package이며 다운로드 할 수 있습니다.foreach 루프 내부에서 변수 또는 환경을 찾을 수없는 함수

#' 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 
} 
+0

어떤 전화를 시도 했습니까? 어떤 주장을하고 있니? 조심해, 우리는 이미 비슷한 질문에 답했다. –

+0

그들은 비슷하지만 똑같지는 않습니다. 그래서 나는 대답하지 않았다고 생각합니다. 나는 여전히 모든 인수를 모든 함수를 통해 전달하는 것을 피하려고 시도하고있다. 실제 모델의 경우 첫 번째 함수에 80 개의 인수를 전달하고 그 중 75 번째를 두 번째 인수로 전달하는 것을 의미합니다 ... 등등. 환경을 제한 할 수있는 방법을 찾아 낼 수 있다면 그 환경에서 일하고 있습니다. 모든 것을 "볼"것입니다. 맞습니까? 그리고 doMPI는 doParallel만큼 복종 할 수 없습니다. 전화가 복잡하기 때문에이 설명에 추가 할 도구가 많지만 github의 드라이버 파일에 있습니다. 죄송합니다. –

답변

0

나는이 문제에 대한 해결책을 Steve Weston의 도움으로 얻을 수있었습니다. 모든 것을 설명하기보다는이 주소의 github에 게시했습니다. https://github.com/jamaas/VarPasMpiExamp.git foreach 루프에 포함 된 함수에 변수 값을 전달하는 한 가지 방법입니다. 이론 상으로는 모든 운영 체제에서 foreach를 사용하여 모든 병렬 백엔드를 사용하여 R에서 작동해야하지만 모든 테스트가 아직 완료되지 않았습니다. 이 버전의 개발 및 테스트는 Ubuntu 16.04 (Debian) Linux에서 수행되었습니다. 이 방법이 효과가 있는지, 특히 더 간단하고 세련된 솔루션이 있다면 알려 주시기 바랍니다.