Невозможно открыть сокеты для параллельного кластера

Я пытаюсь использовать 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 или что-то не так, но все хорошо, что хорошо кончается)

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