Как я могу печатать при использовании%dopar%

У меня есть foreach цикл, который использует %dopar% с doSNOW в качестве фона. Как сделать так, чтобы цикл печатал что-то на каждой итерации?

Мой код ниже - это то, что я сейчас использую, но ничего не печатает.

foreach(ntree=rep(25,2),.combine=combine,.packages='randomForest',
    .inorder=FALSE) %dopar% {
        print("RANDOM FOREST")
        randomForest(classForm,data=data,na.action=na.action,do.trace=do.trace,ntree=ntree,mtry=mtry)
    }   

6 ответов

Решение

Здесь опубликовано несколько хороших решений, но я считаю, что проще всего войти в сокет и использовать отдельный процесс для вывода вызовов журнала в консоль.

Я использую следующую функцию:

log.socket <- make.socket(port=4000)

Log <- function(text, ...) {
  msg <- sprintf(paste0(as.character(Sys.time()), ": ", text, "\n"), ...)
  cat(msg)
  write.socket(log.socket, msg)
}

Затем вы можете поместить записи журнала в коде, например:

Log("Processing block %d of %d", i, n.blocks)

Вывод журнала можно просматривать в режиме реального времени с помощью любого простого инструмента прослушивания сокетов. Например, используя netcat в Linux:

nc -l 4000

Вышеуказанный лог-оператор будет отображаться в терминале netcat как:

2014-06-25 12:30:45: Processing block 2 of 13

Этот метод обладает преимуществом удаленной работы и обеспечивает настолько подробный вывод, насколько вы хотите вести журнал.

ps. Для тех, кто работает в Windows, см . порт netcat от Jon Craton.

pps я угадал write.socket Функция R, вероятно, не является поточно-ориентированной, но если вы не регистрируетесь с высокой частотой, вы вряд ли столкнетесь с какой-либо проблемой. Что-то, чтобы знать, хотя.

Вывод, полученный рабочими снега, по умолчанию отбрасывается, но вы можете использовать опцию makeCluster "outfile", чтобы изменить это. Установка outfile в пустую строку ("") не позволит снегу перенаправить вывод, что часто приводит к выводу ваших сообщений печати, отображаемых на терминале главного процесса.

Просто создайте и зарегистрируйте свой кластер с чем-то вроде:

library(doSNOW)
cl <- makeCluster(4, outfile="")
registerDoSNOW(cl)

Ваш цикл foreach не должен меняться вообще.

Это работает для меня как с кластерами SOCK, так и с кластерами MPI, использующими Rmpi, созданный с помощью Open MPI. В Windows вы не увидите никакого вывода, если используете Rgui. Если вы используете Rterm.exe вместо этого, вы будете.

Обратите внимание, что в дополнение к собственному выводу вы увидите сообщения, созданные снегом, которые также могут быть полезны.


Чтобы использовать индикатор выполнения, doSNOW версии 1.0.14 имеет progress вариант. Вот полный пример:

library(doSNOW)
library(tcltk)
library(randomForest)
cl <- makeSOCKcluster(3)
registerDoSNOW(cl)

ntasks <- 100
pb <- tkProgressBar(max=ntasks)
progress <- function(n) setTkProgressBar(pb, n)
opts <- list(progress=progress)

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

rf <- foreach(ntree=rep(25, ntasks), .combine=combine,
        .multicombine=TRUE, .packages='randomForest',
        .options.snow=opts) %dopar% {
  randomForest(x, y, ntree=ntree)
}

progress Параметр довольно общий, поэтому вы можете просто напечатать сообщение, используя такую ​​функцию, как:

progress <- function(n) cat(sprintf("task %d is complete\n", n))

Функция может принимать 0, 1 или 2 аргумента. Первый предоставленный аргумент - это общее количество выполненных задач, а второй - номер задачи, которая только что завершила.

Простейший пример просто печатает . когда задача завершена:

progress <- function() cat('.')

Этот пример отображает оба аргумента и может использоваться для демонстрации того, что задачи не всегда выполняются по порядку:

progress <- function(nfin, tag) {
  cat(sprintf('tasks completed: %d; tag: %d\n', nfin, tag))
}

Способ, которым я отслеживал прогресс на узлах при длительных операциях, - это создание индикатора выполнения с использованием tkProgressBar от tcltk пакет. Это не совсем то, что вы просили, но это должно позволить вам увидеть что-то из узлов. По крайней мере, это происходит, когда кластер является кластером сокетов, работающим на локальном хосте (который является машиной Windows). Потенциальная проблема заключается в том, что индикатор выполнения либо остается и загромождает ваш монитор, либо он получает closed и распечатанная информация исчезла. Для меня это не было проблемой, так как я просто хотел узнать, каким был текущий статус.

library(parallel)
library(doSNOW)
cl<-makeCluster(detectCores(),type="SOCK")
registerDoSNOW(cl)

Используя ваш код,

foreach(ntree=rep(25,2),.combine=combine,.packages=c('randomForest','tcltk'),
    .inorder=FALSE) %dopar% {
        mypb <- tkProgressBar(title = "R progress bar", label = "",
          min = 0, max = 1, initial = 0, width = 300)
        setTkProgressBar(mypb, 1, title = "RANDOM FOREST", label = NULL)
    ans <- randomForest(classForm,data=data,na.action=na.action,do.trace=do.trace,ntree=ntree,mtry=mtry)
    close(mypb)
    ans
    }

Вот более общий пример использования:

jSeq <- seq_len(30)

foreach(i = seq_len(2), .packages = c('tcltk', 'foreach')) %dopar% {
    mypb <- tkProgressBar(title = "R progress bar", label = "",
        min = 0, max = max(jSeq), initial = 0, width = 300)
    foreach(j = jSeq) %do% {
        Sys.sleep(.1)
        setTkProgressBar(mypb, j, title = "RANDOM FOREST", label = NULL)
    }
    NULL
}

У меня тоже была такая же проблема. Я настраивал параметры для случайного леса, используя пакет foreach, и хотел выводить строку "Результаты" после каждой итерации, но не мог понять, не пройдя отображение индикатора выполнения и т.п.

Вот что я сделал, В своей функции я добавил эту строку

write.table(result, file=paste("RF_ntree_",ntree,"_dims_",dims,".txt", sep=""),
  sep="\t", row.names=F)

Поэтому после каждой итерации результаты записываются в текстовый файл с такими именами, как RF_ntree_250_dims_100.txt.

Поэтому, если я хочу отслеживать прогресс, я просто обновляю папку, в которую записываются текстовые файлы.

PS: результаты накапливаются в кадре данных тоже.

cat("blah-blah-blah\n", file=stdout()) имеет тенденцию работать для меня (linux/emacs/ess). Я думаю, это также работает для некоторых других платформ.

Альтернатива - использовать ведение журнала файлов (например, пакет log4r) и отдельно выводить вывод на экран (например, с помощью tail -f).

Это хорошо работает, если вы все равно планируете создавать логи, и вы можете использовать существующие пакеты со всеми связанными с этим сигналами.

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