假设我有一个代码在foreach循环中执行各种计算,为了简单起见,让它如下所示:
foreach( idx = 1:10 ) %dopar% {
set.seed(idx)
smp <- rnorm(10)
print( sprintf('Index: %d', idx) )
print( cat(sprintf('Value: %f \n', smp[1:10])) )
}代码的主要思想是,它的输出是这样写的,索引只显示一次,然后遵循主代码的各种结果。然后,在使用%do%时,很容易读取日志文件并使用这种结构进行调试,但是使用%dopar%,日志文件会变得杂乱无章。
问:在不改变代码的情况下,是否有办法让每个员工创建自己的输出文件?我刚开始使用doParallel,所以到目前为止我发现的并行输出的唯一方法是使用以下方法:
library(doParallel)
cl <- makeCluster(4, outfile = 'log.txt')
registerDoParallel(cl)但是,outfile只使用一个字符串作为参数,还没有找到将名称向量传递给它的方法。那么,也许有一种方法可以为每个员工指定一个输出文件?
注:在Windows 7上工作。
发布于 2015-09-02 07:14:56
许多解决方案--比如在工作人员中不使用print或在那里指定输出文件--都会浮现出来,但问题是明确要求不更改代码。因此,我假设当前在%dopar%主体中的代码包装在一个不能更改的函数中:
doNotTouch <- function(idx) {
set.seed(idx)
smp <- rnorm(10)
print(sprintf('Index: %d', idx))
cat(sprintf('Value: %f \n', smp[1:10]))
}一种解决方案是在调用doNotTouch之前直接指定输出文件(或者更准确地说:在将输出重定向到特定文件的环境中执行函数):
library(doParallel)
cl <- makeCluster(4)
registerDoParallel(cl)
foreach(idx = 1:10) %dopar% {
capture.output(
doNotTouch(idx),
file = paste0("log", idx, ".txt"))
}
stopCluster(cl)这不会改变问题中提供的代码,而是将其放在一个包装器中,该包装器负责处理正确的输出文件log_[idx].txt。
编辑:在评论中,澄清了问题不是写到单独的文件上,而是关于获得不杂乱无章的输出。在这种情况下,可以在循环中使用return(capture.output(doNotTouch(idx)))来收集属于一起的输出并立即返回它们。此外,@Nutle发现,Sys.getpid()返回一个工人的PID,该PID可用于由工作人员编写单独的日志文件(正如迭代所反对的那样)。
https://stackoverflow.com/questions/32334866
复制相似问题