Параллельный запуск RandomForest на разных узлах кластера

Я хочу запустить randomForest параллельно на кластере (университетском сервере), где я могу одновременно зарезервировать 4 узла, каждый из которых дополнительно содержит 12 ядер. Я использовал пакеты foreach и doSNOW, как указано в описании пакета foreach, но, используя следующий код, я вижу, что вся нагрузка приходится только на первый узел, в то время как для остальных трех узлов потребление памяти отсутствует. Может ли кто-нибудь посоветовать мне, как я могу отредактировать этот код, чтобы каждое ядро ​​каждого узла выполняло одинаковую работу, а затем мы объединяем его в один лес.

> library("foreach")
> library("doSNOW")
> registerDoSNOW(makeCluster(48, type="SOCK"))

> x <- matrix(runif(500), 100)
> y <- gl(2, 50)

> rf <- foreach(ntree = rep(22, 48), .combine = combine, .packages = "randomForest") %dopar%
+    randomForest(x, y, ntree = ntree)
> rf
Call:
randomForest(x = x, y = y, ntree = ntree)
Type of random forest: classification
Number of trees: 1056

person Newbie    schedule 30.08.2016    source источник
comment
Используете ли вы систему пакетной очереди (такую ​​как Torque, LSF или Slurm) для запроса четырех узлов?   -  person Steve Weston    schedule 30.08.2016
comment
Отличный ответ ниже, но я хотел добавить, что вам следует поговорить с администратором университетского кластера. Они смогут помочь вам наилучшим образом для вашего конкретного кластера.   -  person vincentmajor    schedule 30.08.2016


Ответы (1)


Чтобы запустить рабочие процессы на нескольких узлах в кластере SOCK, первым аргументом makeCluster должен быть вектор имен узлов, а не число. В этом случае makeCluster запустит работника на каждом из указанных узлов с помощью команды ssh.

Например, чтобы запустить 12 рабочих процессов на каждом из узлов «n1», «n2», «n3» и «n4», вы можете использовать:

> nodelist <- rep(c("n1", "n2", "n3", "n4"), each=12)
> cl <- makeCluster(nodelist, type="SOCK")
> registerDoSNOW(cl)

Обратите внимание, что имя каждого узла встречается nodelist 12 раз, поэтому длина nodelist равна 48.

Если вы используете систему пакетной очереди для выполнения своего задания, вы должны получить список имен узлов, которые были выделены для вашего задания, а не жестко их кодировать в своем скрипте. Обычно вы можете получить эту информацию из переменной среды, но это зависит от вашей системы пакетной очереди. Например, с помощью Torque вы можете получить список узлов, используя:

> nodelist <- readLines(Sys.getenv("PBS_NODEFILE"))

Я предпочитаю создавать кластер MPI с помощью makeMPIcluster и регистрировать его с помощью doSNOW при выполнении параллельных заданий на кластерах HPC, но этот подход может быть более трудным для новичков. Например, у вас должен быть установлен пакет Rmpi ​​и вы должны выполнить свой сценарий R с помощью команды mpirun. Если вам удастся получить помощь от знающего системного администратора, в долгосрочной перспективе это, вероятно, будет работать лучше.

Еще один подход - использовать параллельный бэкэнд doMPI вместо doSNOW, поскольку doMPI был специально разработан для использования в кластерах HPC. Для получения дополнительной информации см. виньетку doMPI.


Также обратите внимание, что вы получите лучшую производительность, если будете использовать в этом примере аргумент foreach .multicombine=TRUE. Это приведет к тому, что функция combine будет вызываться один раз, а не 47 раз.

person Steve Weston    schedule 30.08.2016
comment
Большое спасибо за подробный ответ. HPC, над которым я работаю, использует OAR Batch Scheduler. Подскажите, как мне получить список узлов в OAR? Во-вторых, вы предлагаете использовать Rmpi ​​вместо doSNOW? Если я использую пакет Rmpi, тогда код для запуска randomForest будет таким же, или мне придется изменить его в соответствии с пакетом Rmpi? - person Newbie; 31.08.2016
comment
@Newbie Я не предлагал вам использовать чистый Rmpi. Я предлагал использовать doSNOW с кластером MPI (созданным с помощью функции makeMPIcluster) или использовать doMPI вместо doSNOW. Оба варианта требуют Rmpi, но вы не используете его напрямую. - person Steve Weston; 31.08.2016
comment
@Newbie Попробуйте использовать переменную среды OAR_NODEFILE. В документации предполагается, что он работает так же, как PBS_NODEFILE, и в этом случае вы можете использовать практически тот же код, что и пример Torque, указанный в моем ответе. - person Steve Weston; 31.08.2016
comment
Я делаю это, но при создании кластера получаю следующую ошибку: Bad owner or permissions on /home/users/tony/.ssh/config - person Newbie; 31.08.2016
comment
@Newbie snow использует ssh для запуска удаленных сотрудников, а права доступа к файлам являются большой проблемой при использовании ssh. Возможно, вам придется удалить любую группу и другие разрешения в конфигурации с помощью такой команды, как chmod go-rwx /home/users/tony/.ssh/config. - person Steve Weston; 31.08.2016