Сохранение объектов R в глобальную среду из вложенной функции, вызываемой родительской функцией с помощью mcmapply - PullRequest
0 голосов
/ 24 января 2020

Я пытаюсь написать R-скрипт, который использует вложенные функции для сохранения нескольких фреймов данных (параллельно) в глобальной среде. Приведенный ниже пример кода отлично работает в Windows. Но когда я переместил этот же код на сервер Linux, объекты, которые функция - prepare_output () сохраняет в глобальную среду, не были захвачены операцией save () в функции - get_output ().

Мне не хватает чего-то, что принципиально отличается от того, как 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 занимает много времени, и я не хочу увеличивать время выполнения путем его выполнения каждые l oop в Подать заявку.

1 Ответ

1 голос
/ 24 января 2020

(Извините, я напишу это как «Ответ», потому что поле для комментариев слишком короткое)

Лучшее решение вашей проблемы - убедиться, что вы вернули объекты, которые вы производите, вместо того, чтобы пытаться назначить их из функции во внешнюю среду [править 2020-01-26], которая никогда не работает в параллельной обработке, потому что параллельные работники не имеют доступа к средам основного Процесс R.

Очень хорошее эмпирическое правило в R, которое поможет вам достичь этого: никогда не используйте assign() или <<- в коде - ни для последовательной, ни для параллельной обработки. В лучшем случае вы можете заставить такой код работать в последовательном режиме, но, в общем, вы получите сложный в обслуживании и подверженный ошибкам код.

Сосредоточившись на , возвращающем значения ( y <- mclapply(...) в вашем примере), вы все сделаете правильно. Он также гораздо лучше вписывается в общий функциональный дизайн R и более естественно распараллеливается.

У меня есть запись в блоге 'Распараллелить For-L oop, переписав его как вызов Lapply ' от 2019-01-11, который может помочь вам перейти к этому функциональному стилю.

...