Переменные в аргументах функции не передаются в кластер при параллельных вычислениях - PullRequest
0 голосов
/ 02 января 2019

У меня возникают трудности с пониманием того, как переменные определяются / передаются в функции при взаимодействии с параллельным пакетом

library(parallel)

test <- function(a = 1){
  no_cores <- detectCores()-1
  clust <- makeCluster(no_cores)
  result <- parSapply(clust, 1:10, function(x){a + x})
  stopCluster(clust)
  return(result)
}

test()
[1]  4  5  6  7  8  9 10 11 12 13

x = 1
test(x)

Error in checkForRemoteErrors(val) : 
3 nodes produced errors; first error: object 'x' not found

test () работает, но test (x) - нет. Когда я изменяю функцию следующим образом, она работает.

test <- function(a = 1){
  no_cores <- detectCores()-1
  clust <- makeCluster(no_cores)
  y = a
  result <- parSapply(clust, 1:10, function(x){y + x})
  stopCluster(clust)
  return(result)
}

x = 1
test(x)

Может кто-нибудь объяснить, что происходит в памяти?

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Я бы предпочел использовать foreach() вместо parSapply():

library(doParallel)

test <- function(a = 1) {
  no_cores <- detectCores() - 1
  registerDoParallel(clust <- makeCluster(no_cores))
  on.exit(stopCluster(clust), add = TRUE)
  foreach(x = 1:10, .combine = 'c') %dopar% { a + x }
}

Вам не нужно заставлять a оцениваться при использовании foreach().Более того, вы можете зарегистрировать параллельный бэкэнд вне функции, если хотите.

См. Руководство по использованию foreach() там (заявление об отказе: я автор tuto).

0 голосов
/ 02 января 2019

Это связано с ленивой оценкой.Аргумент a не оценивается в вызове функции до его первого использования.В первом случае кластер не знает a, поскольку он не был оценен в родительской среде.Вы можете исправить это, форсируя оценку:

test <- function(a = 1){
    no_cores <- detectCores()-1
    clust <- makeCluster(no_cores)
    force(a)    # <------------------------
    result <- parSapply(clust, 1:10, function(x){a + x})
    stopCluster(clust)
    return(result)
}

x = 1
test(x)
#  [1]  2  3  4  5  6  7  8  9 10 11
...