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

问题描述 投票:0回答:1

我正在尝试编写一个R脚本,该脚本使用嵌套函数将多个data.frame(并行)保存到全局环境。下面的示例代码在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调用中每个循环的执行来增加执行时间。

r parallel-processing nested scoping mapply
1个回答
1
投票

(对不起,由于注释框太简短,我将其写为“答案”)

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

R中的一个很好的经验法则将帮助您实现这一目标:切勿在代码中使用assign()<<--既不用于顺序处理,也不用于并行处理。充其量,您可以使这样的代码在顺序模式下工作,但是,总的来说,您将得到难以维护的代码,并且容易出错。

通过关注returning值(在您的示例中为y <- mclapply(...)),您会发现它是正确的。它也更适合R的整体功能设计,并且更自然地并行化。

[我在2019年1月11日收到一篇博客文章'Parallelize a For-Loop by Rewriting it as an Lapply Call',可能会帮助您过渡到这种功能样式。

© www.soinside.com 2019 - 2024. All rights reserved.