使用%dopar%时如何打印

som*_*man 63 parallel-processing foreach r

我有一个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)
    }   
Run Code Online (Sandbox Code Playgroud)

Ste*_*ton 55

默认情况下,snow worker生成的输出会被丢弃,但您可以使用makeCluster"outfile"选项来更改它.将outfile设置为空字符串("")将阻止雪重定向输出,这通常会导致打印消息的输出显示在主进程的终端上.

只需创建和注册您的群集,例如:

library(doSNOW)
cl <- makeCluster(4, outfile="")
registerDoSNOW(cl)
Run Code Online (Sandbox Code Playgroud)

你的foreach循环根本不需要改变.

对于使用使用Open MPI构建的Rmpi的SOCK群集和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)
}
Run Code Online (Sandbox Code Playgroud)

progress选项相当通用,因此您只需使用以下函数打印消息:

progress <- function(n) cat(sprintf("task %d is complete\n", n))
Run Code Online (Sandbox Code Playgroud)

该函数可以采用0,1或2个参数.第一个提供的参数是已完成任务的总数,第二个是刚刚完成的任务的任务编号.

最简单的示例只是.在任务完成时打印:

progress <- function() cat('.')
Run Code Online (Sandbox Code Playgroud)

此示例显示两个参数,可用于演示任务并非始终按顺序完成:

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


hen*_*lst 25

这里发布了许多好的解决方案,但我发现最简单的方法是登录套接字并使用单独的进程在控制台中输出日志调用.

我使用以下功能:

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)
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在代码中放置日志语句,例如:

Log("Processing block %d of %d", i, n.blocks)
Run Code Online (Sandbox Code Playgroud)

可以使用任何简单的套接字监听工具实时查看日志输出.例如,在Linux上使用netcat:

nc -l 4000
Run Code Online (Sandbox Code Playgroud)

以上日志语句将在netcat终端中显示为:

2014-06-25 12:30:45: Processing block 2 of 13
Run Code Online (Sandbox Code Playgroud)

此方法具有远程工作的优点,并提供您需要记录的详细输出.

ps对于Windows上的用户,请参阅Jon Craton的netcat端口.

pps我猜测write.socketR函数可能不是线程安全的,但除非你以高频率登录,否则你不太可能遇到任何问题.但要注意的事情.

  • 需要在Linux终端中运行nc -l 4000,然后才能在R中执行log.sock = make.socket(port = 4000) (3认同)

Ben*_*nes 12

我长时间操作过程中保持轨道上的节点进度的方法是创建一个使用一个进度条,tkProgressBartcltk包.这不是你要求的,但它应该让你从节点中看到一些东西.至少它是在集群是在本地主机(即Windows机器)上运行的套接字集群时执行的.潜在的问题是,进度条要么保持不变,要么使显示器变得杂乱,否则显示close信息就会消失.对我来说,这不是问题,因为我只是想知道当前的状态.

library(parallel)
library(doSNOW)
cl<-makeCluster(detectCores(),type="SOCK")
registerDoSNOW(cl)
Run Code Online (Sandbox Code Playgroud)

使用你的代码,

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
    }
Run Code Online (Sandbox Code Playgroud)

这是一个更通用的例子:

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
}
Run Code Online (Sandbox Code Playgroud)


小智 11

我也有同样的问题.我正在使用foreach包调整随机森林的参数,并希望在每次迭代后打印"结果"行,但如果不经过显示进度条等就无法弄清楚.

这就是我所做的,在我的功能中,我添加了这一行

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

因此,在每次迭代之后,结果都会写入一个名为RF_ntree_250_dims_100.txt的文本文件.

因此,如果我想跟踪进度,我只需刷新正在写入文本文件的文件夹.

PS:结果也在数据框中累积.