如何使用%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) }
在这里发布了很多很好的解决scheme,但是我发现login套接字并使用单独的进程在控制台中输出日志调用是最容易的。
我使用以下函数:
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)
日志输出可以使用任何简单的套接字侦听工具实时查看。 例如,在Linux上使用netcat:
nc -l 4000
上面的日志语句将显示在netcatterminal中:
2014-06-25 12:30:45: Processing block 2 of 13
此方法具有远程工作的优点,并提供了您关心logging的详细输出。
ps对于那些在Windows上,请参阅Jon Craton的netcat端口 。
PPS我猜write.socket
R函数可能不是线程安全的,但除非你logging在高频率,你不可能遇到任何问题。 有些事情要注意。
由snow worker产生的输出默认被扔掉,但是你可以使用makeCluster的“outfile”选项来改变它。 将outfile设置为空string(“”)将防止下雪redirect输出,通常会导致从主消息的terminal显示打印消息的输出。
只需创build并注册您的群集:
library(doSNOW) cl <- makeCluster(4, outfile="") registerDoSNOW(cl)
你的foreach循环根本不需要改变。
这适用于使用使用Open MPI构build的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) }
progress
选项是相当普遍的,所以你可以简单地使用一个函数来打印消息,例如:
progress <- function(n) cat(sprintf("task %d is complete\n", n))
在长时间运行期间,我跟踪节点进度的一种方法是使用tcltk
包中的tcltk
创build一个进度条。 这不是你所要求的,但它应该让你看到节点的东西。 至less当集群是在本地主机(这是一台Windows机器)上运行的套接字集群的时候。 潜在的问题是进度条要么保持不变,要么让显示器混乱,要么close
d,打印的信息不见了。 对我来说,这不是问题,因为我只是想知道目前的状况。
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包调整随机森林的参数,并希望在每次迭代之后打印一个“Results”行,但是不经过显示进度条等就不能弄清楚。
这就是我所做的,在我的function中,我添加了这一行
write.table(result, file=paste("RF_ntree_",ntree,"_dims_",dims,".txt", sep=""), sep="\t", row.names=F)
因此,每次迭代之后,结果都会写入一个名称为RF_ntree_250_dims_100.txt的文本文件。
所以如果我想跟踪进度,我只是刷新文本文件被写入的文件夹。
PS:结果也是在一个数据框中累积的。
另一种方法是使用文件日志logging(例如log4r软件包),并单独在屏幕上打印输出(例如,通过'tail -f')。
如果你考虑创build日志,这个效果很好,你可以使用现有的软件包和所有相关的花里胡哨的东西。