ПРИМЕЧАНИЯ: Это маловероятно, хорошее использование параллельного Еогеаспа АиРа, но я отвечу на ваш вопрос, а затем объяснить, почему. (BTW, когда я использую «кластер» в этом ответе, я имею в виду кластер H2O (даже если это только на вашей локальной машине), а не кластер R ».)
Я переписал ваши код, предполагая, что намерение было иметь одного H2O кластера, где все модели должны быть сделаны:
library(foreach)
library(doParallel)
library(doSNOW)
library(h2o)
h2o.init(ip="localhost", nthreads=-1, max_mem_size = "5G")
Xtr.hf = as.h2o(Xtr)
Xval.hf = as.h2o(Xval)
cl = makeCluster(6, type="SOCK")
registerDoSNOW(cl)
junk <- foreach(i=1:6,
.packages=c("h2o"),
.errorhandling = "stop",
.verbose=TRUE) %dopar%
{
for (j in 1:3) {
bm2 <- h2o.gbm(
training_frame = Xtr.hf,
validation_frame = Xval.hf,
x=2:ncol(Xtr.hf),
y=1,
distribution="gaussian",
ntrees = 100,
max_depth = 3,
learn_rate = 0.1,
nfolds = 1)
#TODO: do something with bm2 here?
}
return(iname) #???
}
stopCluster(cl)
Т.е. в виде набросков:
- Пуск H2O и нагрузки
Xtr
и Xval
в него
- Start 6 потоков в вашем R клиента
- В каждой нити делают 3 модели GBM (один за другим)
Я опустил команду h2o.shutdown()
, угадывая, что вы этого не предполагали (когда вы завершаете кластер H2O, вы только что удалили модели). И я подсказал, где вы можете что-то делать с вашей моделью. И я дал H2O все потоки на вашей машине (то есть nthreads=-1
в h2o.init()
), а не только 2.
Вы можете сделать модели H2O параллельно, но это, как правило, плохая идея, так как они в конечном борьба за ресурсы. Лучше делать их по одному и полагаться на собственный параллельный код H2O для распространения вычислений по кластеру. (Когда кластер является одиночной машиной, это имеет тенденцию быть очень эффективным.)
По факту, что вы столкнулись с проблемой создания параллельной петли в R, заставляет меня думать, что вы пропустили путь H2O: это сервер, написанный на Java, а R - просто легкий клиент, который отправляет ему вызовы API. Расчеты GBM не выполняются в R; все они выполнены в Java-коде.
Другим способом интерпретации кода является запуск нескольких экземпляров H2O, то есть нескольких кластеров H2O. Это может быть хорошей идеей, если у вас есть набор машин, и вы знаете, что алгоритм H2O не очень хорошо масштабируется в многоузловом кластере. Выполнение этого на одной машине - почти наверняка плохая идея. Но, ради аргумента, это то, как вы это делаете (непроверенным):
library(foreach)
library(doParallel)
library(doSNOW)
cl = makeCluster(6, type="SOCK")
registerDoSNOW(cl)
junk <- foreach(i=1:6,
.packages=c("h2o"),
.errorhandling = "stop",
.verbose=TRUE) %dopar%
{
library(h2o)
h2o.init(ip="localhost", port = 54321 + (i*2), nthreads=2, max_mem_size = "5G")
Xtr.hf = as.h2o(Xtr)
Xval.hf = as.h2o(Xval)
for (j in 1:3) {
bm2 <- h2o.gbm(
training_frame = Xtr.hf,
validation_frame = Xval.hf,
x=2:ncol(Xtr.hf),
y=1,
distribution="gaussian",
ntrees = 100,
max_depth = 3,
learn_rate = 0.1,
nfolds = 1)
#TODO: save bm2 here
}
h2o.shutdown(prompt=FALSE)
return(iname) #???
}
stopCluster(cl)
Теперь контур является:
- Создать-R темы
- В каждом потоке, начать H2O кластер, который работает на localhost, но на порт, уникальный для этого кластера. (
i*2
- это потому, что каждый кластер H2O фактически использует два порта.)
- Загрузите свои данные в кластер H2O (т. Е. Это будет повторяться 6 раз, один раз для каждого кластера).
- Сделайте 3 модели GBM, один за другим.
- Сделайте что-нибудь с этими моделями
- Убить кластер для текущей темы.
Если у вас есть 12+ нитей на вашей машине, и 30+ ГБ памяти, и данные относительно мал, то это будет примерно так эффективно, как с помощью одного кластера H2O и делает 12 моделей GBM в последовательный. Если нет, я считаю, что это будет хуже. (Но если у вас есть 6 кластеров H2O на 6 удаленных машинах, это может быть полезным подходом - я должен признать, что мне было интересно, как это сделать, и использование параллельной библиотеки для него никогда не приходило в голову до тех пор, пока Я видел ваш вопрос)
Примечание: в текущей версии (3.10.0.6), я знаю, приведенный выше код не будет работать, так как есть в h2o.init()
a bug, что фактически означает, что игнорирование порта. (Временные решения: либо предварительно запустить все 6 кластеров H2O в командной строке, либо установить порт в переменной окружения.)
Спасибо за объяснение. Таким образом, единственное различие между вашими кодами и моими: 'h2o.init (ip =" localhost ", port = 54321 + (i * 2), ...)'. Назначая другой порт, h2o создает отдельный кластер для каждого потока. – horaceT
@horaceT Кроме того, загрузка данных 'as.h2o()' должна проходить внутри цикла for. (Я также поместил библиотеку (h2o) 'внутри цикла foreach, хотя я не уверен, что это было необходимо.) (Как уже отмечалось, код не будет работать до тех пор, пока ошибка порта не будет исправлена.) –
У меня есть не проверял, но я просто хочу понять концепцию. Вызов 'h2o.init (...)' создает кластер, и каждый кластер привязывается к одному и только одному потоку. Я не могу иметь несколько потоков, работающих внутри одного и того же кластера. Так оно и должно работать? – horaceT