Запуск 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.