Запуск doRedis- объект не найден, даже если он был экспортирован

Я тестирую пакет doRedis, запустив рабочий компьютер на одной машине и мастер / сервер на другой. Код моего мастера выглядит так:

 #Register ...
 r <- foreach(a=1:numreps, .export(...)) %dopar% {
        train <- func1(..)

        best <- func2(...)

        weights <- func3(...)

        return ...
      }

В каждой функции глобальная переменная доступна, но не модифицируется. Я экспортировал глобальную переменную в часть.export цикла foreach, но всякий раз, когда я запускаю код, возникает ошибка, указывающая, что переменная не найдена. Интересно, что код работает, когда все мои работники на одной машине, но вылетает, когда у меня есть "внешний" работник. Любые идеи, почему эта ошибка происходит, и как ее исправить?

Спасибо!

ОБНОВЛЕНИЕ: у меня есть суть некоторого кода здесь: https://gist.github.com/liangricha/fbf29094474b67333c3b

ОБНОВЛЕНИЕ 2: Я задал еще один вопрос, связанный с doRedis: "Возможно ли, чтобы каждая рабочая машина использовала все свои ядра?

@ Стив Вестон ответил: "Запуск одного работника Redis на ядро ​​часто полностью использует машину".

1 ответ

Решение

Этот вид кода был проблемой для пакетов doParallel, doSNOW и doMPI в прошлом, но они были улучшены в прошлом году или около того, чтобы справиться с этим лучше. Проблема в том, что переменные экспортируются в специальную "экспортную" среду, а не в глобальную среду. Это предпочтительно по-разному, но это означает, что бэкэнд должен выполнять больше работы, чтобы экспортируемые переменные находились в области действия экспортируемых функций. Похоже, doRedis не был обновлен для использования этих улучшений.

Вот простой пример, который иллюстрирует проблему:

library(doRedis)
registerDoRedis('jobs')
startLocalWorkers(3, 'jobs')
glob <- 6
f1 <- function() {
  glob
}
f2 <- function() {
  foreach(1:3, .export=c('f1', 'glob')) %dopar% {
    f1()
  }
}

f2()  # fails with the error: "object 'glob' not found"

Если используется doParallel backend, он завершается успешно:

library(doParallel)
cl <- makePSOCKcluster(3)
registerDoParallel(cl)

f2()  # works with doParallel

Одним из обходных путей является определение функции "f1" внутри функции "f2":

f2 <- function() {
  f1 <- function() {
    glob
  }
  foreach(1:3, .export=c('glob')) %dopar% {
    f1()
  }
}

f2()  # works with doParallel and doRedis

Другое решение состоит в том, чтобы использовать некоторый механизм для экспорта переменных в глобальную среду каждого из работников. С doParallel или doSNOW вы можете сделать это с помощью функции clusterExport, но я не уверен, как это сделать с помощью doRedis.

Я сообщу об этой проблеме автору пакета doRedis и предложу обновить doRedis для обработки экспортированных функций, таких как doParallel.

Другие вопросы по тегам