Невозможно открыть сокеты для параллельного кластера
Я пытаюсь использовать parallel
пакет, и обнаружил, что makeCluster
не в состоянии завершить. Я проследил зависание до следующей строки в newPSOCKnode
:
con <- socketConnection("localhost", port = port, server = TRUE,
blocking = TRUE, open = "a+b", timeout = timeout)
Эта команда останавливается (если время ожидания по умолчанию является большим значением). Я подозреваю, что это связано с некоторыми "чрезмерными ИТ-правилами", установленными на наших рабочих компьютерах, но я бы приветствовал любые предложения относительно того, как отследить (и исправить) источник проблемы. Это Windows7-64, "Enterprise", R 3.0.1 .
Больше информации: внутри сеанса отладки я установил timeout < - 10
, но все равно зависает - как будто socketConnection
оказывается в ловушке где-то, что он даже не может проверить значение тайм-аута.
Вот мой дамп в той же точке, что и данные Ричи Коттона:
Browse[3]> ls.str()
arg : chr "parallel:::.slaveRSOCK()"
cmd : chr "\"C:/Users/carl.witthoft/Documents/R/R-3.0.1/bin/x64/Rscript\" -e \"parallel:::.slaveRSOCK()\" MASTER=localhost PORT=11017 OUT="| __truncated__
env : chr "MASTER=localhost PORT=11017 OUT=/dev/null TIMEOUT=2592000 METHODS=TRUE XDR=TRUE"
machine : chr "localhost"
manual : logi FALSE
master : chr "localhost"
methods : logi TRUE
options : <environment: 0x000000000ccac6a0>
outfile : chr "/dev/null"
port : int 11017
rank : int 1
renice : int NA
rscript : chr "\"C:/Users/carl.witthoft/Documents/R/R-3.0.1/bin/x64/Rscript\""
timeout : num 2592000
useXDR : logi TRUE
Таким образом, кроме другого номера порта, я думаю, что все совпадает.
Следующий трюк: я открыл снаряд и побежал netsh advfirewall firewall add rule name="Open Port 11017" dir=in action=allow protocol=TCP localport=11017
и получил ответ "ОК". Я побежал netstat -a -n
и нашел следующую строку:
TCP 0.0.0.0:11017 0.0.0.0:0 LISTENING
Но работает makePSOCKcluster
все еще висит на том же месте.
ДАЛЕЕ: пробовал бегать R
из командной строки (через Cygwin Bash), и я получаю сообщение об ошибке Error in loadhistory(file) : no history mechanism available
Execution halted
после чего -C возвращает меня в R-приглашение.
3 ответа
То, что вы описываете, является классической проблемой с кластерами PSOCK: makeCluster
виснет Он может зависать по десяткам причин, потому что он должен создать все процессы, называемые "рабочими" процессами, которые будут выполнять фактическую работу "кластера", и это включает в себя запуск новых R-сеансов с использованием команды Rscript, которая выполнит .slaveRSOCK
функция, которая создаст соединение сокета обратно к мастеру и затем выполнит slaveLoop
функция, в которой он в конечном итоге будет выполнять задачи, отправленные ему мастером. Если что-то пойдет не так при запуске любого из рабочих процессов (и поверьте мне: многое может пойти не так), мастер зависнет при выполнении socketConnection
в ожидании подключения рабочего к нему, даже если этот работник, возможно, умер или даже не был успешно создан.
Для многих сценариев отказа, используя outfile
Аргумент велик, потому что он часто выявляет ошибку, которая приводит к смерти рабочего процесса и, следовательно, к зависанию мастера. Но если это ничего не показывает, я перехожу в ручной режим. В ручном режиме мастер печатает команду для запуска каждого рабочего вместо выполнения самой команды. Это больше работы, но она дает вам полный контроль, и вы можете даже отлаживать в рабочих, если вам нужно.
Вот пример:
> library(parallel)
> cl <- makePSOCKcluster(1, manual=TRUE, outfile='log.txt')
Manually start worker on localhost with
'/usr/lib/R/bin/Rscript' -e 'parallel:::.slaveRSOCK()' MASTER=localhost
PORT=10187 OUT=log.txt TIMEOUT=2592000 METHODS=TRUE XDR=TRUE
На этом этапе ваш сеанс R зависает, потому что он выполняет socketConnection
так же, как вы описали. Теперь ваша задача - открыть новое окно терминала (командную строку или что-то еще) и вставить в эту команду Rscript. Как только вы выполнили это, makePSOCKcluster
должен вернуться, так как мы просили только одного работника. Конечно, если что-то пойдет не так, оно не вернется, но если вам повезет, вы получите сообщение об ошибке в окне терминала и получите важную подсказку, которая, надеюсь, приведет к решению вашей проблемы., Если вам не повезет, команда Rscript также будет зависать, и вам придется погрузиться еще глубже.
Чтобы отладить работника, вы не выполняете отображаемую команду Rscript, потому что вам нужен интерактивный сеанс. Вместо этого вы начинаете сеанс R с помощью такой команды:
$ R --vanilla --args MASTER=localhost PORT=10187 OUT=log.txt TIMEOUT=2592000 METHODS=TRUE XDR=TRUE
В этом сеансе R вы можете установить точку останова на .slaveRSOCK
функцию, а затем выполните ее:
> debug(parallel:::.slaveRSOCK)
> parallel:::.slaveRSOCK()
Теперь вы можете начать пошаговое выполнение кода, возможно установив точки останова на slaveLoop
а также makeSOCKmaster
функции. В вашем случае, я предполагаю, что он будет зависать, пытаясь создать сокет-соединение, и в этом случае название вашего вопроса будет уместным.
Для получения дополнительной информации об этой проблеме см. Мой ответ на аналогичный вопрос.
ОБНОВИТЬ
Теперь, когда эта конкретная проблема решена, я могу добавить две подсказки для отладки makePSOCKcluster
проблемы:
- Проверьте, работает ли что-либо в вашем.Rprofile только в интерактивном режиме.
- В Windows используйте команду Rterm, а не Rgui, так что вы с большей вероятностью увидите сообщения об ошибках и результаты использования
outfile=''
,
Тест 1: работает ли очевидная команда?
library(parallel)
cluster <- makePSOCKcluster("localhost")
parSapply(cluster, 1:5, sqrt)
stopCluster(cluster)
Тест 2: Ваш порт заблокирован?
В соответствии с ?makeCluster
порт по умолчанию 10187
, Узнайте у администратора сети, открыт ли этот порт.
Тест 3: передают ли переменные socketConnection
смотреть прямо?
Если я сделаю debugonce(parallel:::newPSOCKnode)
а затем переходит к непосредственно перед вызовом socketConnection
Рабочее пространство выглядит так:
ls.str()
arg : chr "parallel:::.slaveRSOCK()"
## cmd : chr "\"C:/PROGRA~1/R/R-215~1.2/bin/x64/Rscript\" -e \"parallel:::.slaveRSOCK()\" MASTER=localhost PORT=10187 OUT=/dev/null TIMEOUT=2"| __truncated__
## env : chr "MASTER=localhost PORT=10187 OUT=/dev/null TIMEOUT=2592000 METHODS=TRUE XDR=TRUE"
## machine : chr "localhost"
## manual : logi FALSE
## master : chr "localhost"
## methods : logi TRUE
## options : <environment: 0x0000000010bf2518>
## outfile : chr "/dev/null"
## port : num 10187
## rank : int 1
## renice : int NA
## rscript : chr "\"C:/PROGRA~1/R/R-215~1.2/bin/x64/Rscript\""
## timeout : num 2592000
## useXDR : logi TRUE
Ты получаешь то же самое?
Ну, я не чувствую себя полным идиотом.
Я вернулся к "Три R отладки программного обеспечения" (Retry, Reboot, Reload), и после перезагрузки моей системы и успешного запуска автозагрузки вручную, я попытался создать кластер с manual=FALSE
и имел немедленный успех там же.
РЕДАКТИРОВАТЬ: я должен дать понять, что изменение моего .Rprofile
от loadhistory()
в if(interactive() ) loadhistory()
имеет решающее значение для успешного использования cluster
функции.
Я очень благодарен Ричи и Стиву за все их полезные комментарии и предложения. Я, конечно, выучил кучу вещей "под капотом", так что опыт был довольно положительным, по крайней мере, для меня.
(Так что я не знаю, что мешало WindowsOS или что-то не так, но все хорошо, что хорошо кончается)