R: как цикл foreach находит функцию, которая должна быть вызвана? - программирование
Подтвердить что ты не робот

R: как цикл foreach находит функцию, которая должна быть вызвана?

У меня проблемы, когда я использую цикл foreach (используя %dopar%), который вызывает самоопределяемую функцию. На самом деле не проблема, когда я работаю с Linux, но когда я использую Windows, самоопределяемая функция не может быть найдена. Трудно объяснить проблему словами, поэтому я составил небольшой пример, чтобы показать это. Предположим, что у меня есть набор из трех простых функций, где FUN2 (используя %do%) и FUN3 (используя %dopar%) вызывает первый (FUN):

FUN <- function(x,y,z) { x + y + z }
FUN2 <- function(a, b) {
  foreach(i=1:3) %do% FUN(i, a, b)
}
FUN3 <- function(a, b) {
  foreach(i=1:3) %dopar% FUN(i, a, b)
}

Функции хранятся в script, называемом foreach_testfunctions.R. В другом script (foreach.test) я отправлю эти функции, используйте library(doParallel) и попытайтесь использовать эти функции. Сначала я делаю это с Linux, и все работает нормально:

source("foreach_testfunctions.R")
a <- 2
b <- 3
library(doParallel)
registerDoParallel()

foreach(i=1:3) %do% FUN(i, a, b)    ## works fine
FUN2(a, b)                          ## works fine
foreach(i=1:3) %dopar% FUN(i, a, b) ## works fine
FUN3(a, b)                          ## works fine 

Затем я делаю это в Windows:

source("foreach_testfunctions.R")
a <- 2
b <- 3
library(doParallel)
cl <- makeCluster(3)
registerDoParallel(cl)

foreach(i=1:3) %do% FUN(i, a, b)    ## works fine
FUN2(a, b)                          ## works fine
foreach(i=1:3) %dopar% FUN(i, a, b) ## works fine
FUN3(a, b)                          ## does not work
Error in FUN(i, a, b) : task 1 failed - "Could not find function "FUN""

Заключение: (1) Нет проблем с %do%. (2) Проблемы с %dopar% при использовании Windows. Я попытался вставить строку clusterExport(cl, varlist=c("FUN", "a", "b"), env=environment()) перед строкой, которая вызывает FUN3, чтобы убедиться, что функция FUN и переменные a и b найдены в соответствующей среде, но ошибка остается.

Мои вопросы: Почему Windows ведет себя иначе, чем Linux, хотя код идентичен (кроме синтаксиса registerDoParallel)? Как я могу убедиться, что Windows выполняет найти функцию FUN при вызове через функцию FUN3?

4b9b3361

Ответ 1

Они ведут себя по-другому, потому что registerDoParallel регистрирует бэкэнд mclapply в Linux, в то время как он регистрирует бэкэнд clusterApplyLB в Windows. При использовании бэкэнд mclapply, по сути, нет проблем с экспортом данных, поэтому он работает в Linux. Но с clusterApplyLB вы можете столкнуться с проблемами, если foreach не выполняет автоматический экспорт требуемых функций и данных.

Вы можете решить эту проблему, изменив FUN3 на экспорт FUN с помощью опции .export:

FUN3 <- function(a, b) {
  foreach(i=1:3, .export='FUN') %dopar% FUN(i, a, b)
}

Это решение работает как в Linux, так и в Windows, поскольку .export игнорируется бэкэнд mclapply.

Как указано Hong Ooi, у вас есть ошибка в использовании clusterExport, но я бы не использовал clusterExport для решения проблемы, так как она специфична для бэкэнд.

Ответ 2

В своем вызове clusterExport удалите часть env=environment(). То, что вы делаете, говорит clusterExport искать ваши объекты в совершенно новой среде, поэтому, естественно, их не найти.