繁体   English   中英

使用 mcmapply 从父函数调用的嵌套函数内部将 R 对象保存到全局环境

[英]Saving R objects to global environment from inside a nested function called by a parent function using mcmapply

我正在尝试编写一个使用嵌套函数将多个 data.frames(并行)保存到全局环境的 R 脚本。 下面的示例代码在 Windows 中运行良好。 但是,当我将相同的代码移动到 Linux 服务器时,函数-prepare_output() 保存到全局环境的对象不会被函数-get_output() 中的 save() 操作捕获。

我是否遗漏了与 mcmapply 如何影响 Linux 与 Windows 中的范围的根本不同的东西?

library(data.table)
library(parallel)

#Function definitions
default_case <- function(flag){
  if(flag == 1){
    create_input()
    get_output()
  }else{
    Print("select a proper flag!")
  }
}

create_input <- function(){
  dt_initial <<- data.table('col1' = c(1:20), 'col2' = c(21:40)) #Assignment to global envir
}


get_output<- function(){

  list1 <- c(5,6,7,8)
  dt1 <- data.table(dt_initial[1:15,])

  prepare_output<- function(cnt){
    dt_new <- data.table(dt1)
    dt_new <- dt_new[col1 <= cnt,  ]
    assign(paste0('dt_final_',cnt), dt_new, envir =  .GlobalEnv )
    #eval(call("<<-",paste0('dt_final_',cnt), dt_new))

    print('contents in global envir inside:')
    print(ls(name = .GlobalEnv)) # This print all object names dt_final_5 through dt_final_8 correctly
  }

  mcmapply(FUN = prepare_output,list1,mc.cores = globalenv()$numCores)


  print('contents in global envir outside:')
  print(ls(name = .GlobalEnv)) #this does NOT print dataframes generated and assigned to global in function prepare_output

  save( list = ls(name = .GlobalEnv)[ls(name = .GlobalEnv) %like% 'dt_final_' ], file = 'dt_final.Rdata')
}

if(Sys.info()['sysname'] == "Windows"){numCores <- 1}else{numCores <- parallel::detectCores()}
print('numCores:')
print(numCores)

#Function call
default_case(1)

我使用嵌套结构的原因是因为dt1的准备需要时间,我不想通过在 apply 调用中的每个循环执行来增加执行时间。

(抱歉,我将其写为“答案”,因为评论框太简短了)

您的问题的最佳解决方案是确保您返回您生成的对象,而不是尝试它们从函数内部分配给外部环境 [edit 2020-01-26] 外部环境在并行处理中永远不会工作,因为并行工作人员不会可以访问主 R 进程的环境。

R 中的一个非常好的经验法则可以帮助您实现这一点:切勿在代码中使用assign()<<- - 无论是顺序处理还是并行处理。 充其量,您可以让此类代码在顺序模式下工作,但一般来说,您最终会得到难以维护且容易出错的代码。

通过专注于返回值( y <- mclapply(...)在您的示例中),您会得到正确的。 它也更适合 R 的整体功能设计,并且更自然地并行化。

我在2019 年1 月 11 日发表了一篇博文“通过将 For 循环重写为 Lapply 调用来并行化它 ,它可能会帮助您过渡到这种函数式风格。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM